コード例 #1
0
        /// <summary>
        /// Registers the specified object with the tree.
        /// </summary>
        private bool RegisterGameObject(GameObject gameObject)
        {
            if (!CanGameObjectBeRegisteredWithTree(gameObject))
            {
                return(false);
            }

            // Build the object's sphere
            Box      objectWorldBox = gameObject.GetWorldBox();
            Sphere3D objectSphere   = objectWorldBox.GetEncapsulatingSphere();

            // Add the object as a terminal node. Also store the node in the dictionary so that we can
            // use it when it's needed.
            SphereTreeNode <GameObject> objectNode = _sphereTree.AddTerminalNode(objectSphere, gameObject);

            _gameObjectToNode.Add(gameObject, objectNode);

            #if !USE_TRANSFORM_HAS_CHANGED
            _gameObjectToTransformData.Add(gameObject, GetGameObjectTransformData(gameObject));
            #endif

            // If it is a mesh object, start silent building the mesh
            if (gameObject.HasMesh())
            {
                EditorMesh editorMesh = EditorMeshDatabase.Instance.CreateEditorMesh(gameObject.GetMesh());
                if (editorMesh != null)
                {
                    EditorMeshDatabase.Instance.AddMeshToSilentBuild(editorMesh);
                }
            }

            EditorCamera.Instance.AdjustObjectVisibility(gameObject);
            return(true);
        }
コード例 #2
0
        /// <summary>
        /// Returns a list that contains all terminal nodes that intersect or are fully
        /// encapsulated by the specified sphere.
        /// </summary>
        public List <SphereTreeNode <T> > OverlapSphere(Sphere3D sphere)
        {
            var overlappedTerminalNodes = new List <SphereTreeNode <T> >(20);

            OverlapSphereRecurse(sphere, _rootNode, overlappedTerminalNodes);
            return(overlappedTerminalNodes);
        }
コード例 #3
0
 /// <summary>
 /// Recursive method which is used to step down the tree hierarchy collecting all terminal nodes
 /// which are overlapped by the specified sphere.
 /// </summary>
 private void OverlapSphereRecurse(Sphere3D sphere, SphereTreeNode <T> parentNode, List <SphereTreeNode <T> > overlappedTerminalNodes)
 {
     // If the parent is not overlapped there is no need to go any further
     if (!parentNode.Sphere.OverlapsFullyOrPartially(sphere))
     {
         return;
     }
     else
     {
         // If this is a terminal node, add it to the output list and return
         if (parentNode.IsTerminal)
         {
             overlappedTerminalNodes.Add(parentNode);
             return;
         }
         else
         {
             // Recurs for each child node
             List <SphereTreeNode <T> > childNodes = parentNode.Children;
             foreach (SphereTreeNode <T> childNode in childNodes)
             {
                 OverlapSphereRecurse(sphere, childNode, overlappedTerminalNodes);
             }
         }
     }
 }
コード例 #4
0
        /// <summary>
        /// Adds a terminal node to the tree.
        /// </summary>
        /// <remarks>
        /// The function does not integrate the node inside the sphere hierarchy. It
        /// will only add it to the integration pending queue. The actual integration
        /// process will be performed inside 'PerformPendingUpdates'.
        /// </remarks>
        /// <param name="sphere">
        /// The node's sphere.
        /// </param>
        /// <param name="data">
        /// The node's data.
        /// </param>
        /// <returns>
        /// The node which was added to the tree.
        /// </returns>
        public SphereTreeNode <T> AddTerminalNode(Sphere3D sphere, T data)
        {
            // Create a new node and mark it as terminal
            var newTerminalNode = new SphereTreeNode <T>(sphere, this, data);

            newTerminalNode.SetFlag(SphereTreeNodeFlags.Terminal);

            // Add the node to the integration queue
            AddNodeToIntegrationQueue(newTerminalNode);

            return(newTerminalNode);
        }
コード例 #5
0
        public bool OverlapsFullyOrPartially(Sphere3D sphere)
        {
            float distanceBetweenCenters = GetDistanceBetweenCenters(sphere);

            // Fully?
            if (distanceBetweenCenters + sphere.Radius <= _radius)
            {
                return(true);
            }

            // Partially?
            return(distanceBetweenCenters - sphere.Radius <= _radius);
        }
コード例 #6
0
        public Sphere3D Encapsulate(Sphere3D sphere)
        {
            float distanceBetweenCenters = GetDistanceBetweenCenters(sphere);

            float newDiameter = distanceBetweenCenters + _radius + sphere.Radius;
            float newRadius   = newDiameter * 0.5f;

            Vector3 fromThisToOther = sphere.Center - Center;

            fromThisToOther.Normalize();
            Vector3 newCenter = Center - fromThisToOther * _radius + fromThisToOther * newRadius;

            return(new Sphere3D(newCenter, newRadius));
        }
コード例 #7
0
        /// <summary>
        /// Handles the transform change for the specified object transform.
        /// </summary>
        private void HandleObjectTransformChange(Transform gameObjectTransform)
        {
            // Just ensure that the object is registered with the tree
            GameObject gameObject = gameObjectTransform.gameObject;

            if (!IsGameObjectRegistered(gameObject))
            {
                return;
            }

            // Store the object's node for easy access. We will need to instruct the
            // tree to update this node as needed.
            SphereTreeNode <GameObject> objectNode = _gameObjectToNode[gameObject];

            // We will first have to detect what has changed. So we will compare the
            // object's sphere as it is now with what was before.
            bool     updateCenter   = false;
            bool     updateRadius   = false;
            Sphere3D previousSphere = objectNode.Sphere;
            Sphere3D currentSphere  = gameObject.GetWorldBox().GetEncapsulatingSphere();

            // Detect what changed
            if (previousSphere.Center != currentSphere.Center)
            {
                updateCenter = true;
            }
            if (previousSphere.Radius != currentSphere.Radius)
            {
                updateRadius = true;
            }

            // Call the appropriate node update method
            if (updateCenter && updateRadius)
            {
                _sphereTree.UpdateTerminalNodeCenterAndRadius(objectNode, currentSphere.Center, currentSphere.Radius);
            }
            else if (updateCenter)
            {
                _sphereTree.UpdateTerminalNodeCenter(objectNode, currentSphere.Center);
            }
            else if (updateRadius)
            {
                _sphereTree.UpdateTerminalNodeRadius(objectNode, currentSphere.Radius);
            }

            EditorCamera.Instance.AdjustObjectVisibility(gameObject);
        }
コード例 #8
0
        /// <summary>
        /// Returns a list of all objects which are overlapped by the specified sphere.
        /// </summary>
        /// <param name="sphere">
        /// The sphere involved in the overlap query.
        /// </param>
        /// <param name="objectOverlapPrecision">
        /// The desired overlap precision. For the moment this is not used.
        /// </param>
        public List <GameObject> OverlapSphere(Sphere3D sphere, ObjectOverlapPrecision objectOverlapPrecision = ObjectOverlapPrecision.ObjectBox)
        {
            // Retrieve all the sphere tree nodes which are overlapped by the sphere. If no nodes are overlapped,
            // we can return an empty list because it means that no objects could possibly be overlapped either.
            List <SphereTreeNode <GameObject> > allOverlappedNodes = _sphereTree.OverlapSphere(sphere);

            if (allOverlappedNodes.Count == 0)
            {
                return(new List <GameObject>());
            }

            // Loop through all overlapped nodes
            var overlappedObjects = new List <GameObject>();

            foreach (SphereTreeNode <GameObject> node in allOverlappedNodes)
            {
                // Store the node's object for easy access
                GameObject gameObject = node.Data;

                // Note: It is important to check for null because the object may have been destroyed. 'RemoveNullObjectNodes'
                //       removes null objects but given the order in which Unity calls certain key functions such as 'OnSceneGUI'
                //       and any editor registered callbacks, null object references can still pop up.
                if (gameObject == null)
                {
                    continue;
                }
                if (!gameObject.activeSelf)
                {
                    continue;
                }

                // We need to perform an additional check. Even though the sphere overlaps the object's node (which is
                // another sphere), we must also check if the sphere overlaps the object's world oriented box. This allows
                // for better precision.
                OrientedBox objectWorldOrientedBox = gameObject.GetWorldOrientedBox();
                if (sphere.OverlapsFullyOrPartially(objectWorldOrientedBox))
                {
                    overlappedObjects.Add(gameObject);
                }
            }

            return(overlappedObjects);
        }
コード例 #9
0
ファイル: EditorScene.cs プロジェクト: swipswaps/VoloAirsport
 public List <GameObject> OverlapSphere(Sphere3D sphere, ObjectOverlapPrecision overlapPrecision = ObjectOverlapPrecision.ObjectBox)
 {
     return(_gameObjectSphereTree.OverlapSphere(sphere, overlapPrecision));
 }
コード例 #10
0
 public SphereTreeNode(Sphere3D sphere, SphereTree <T> tree, T data = default(T))
 {
     _tree   = tree;
     _data   = data;
     _sphere = sphere;
 }
コード例 #11
0
 public void Encapsulate(SphereTreeNode <T> node)
 {
     _sphere = _sphere.Encapsulate(node.Sphere);
 }
コード例 #12
0
 public float GetDistanceBetweenCentersSq(Sphere3D sphere)
 {
     return((Center - sphere.Center).sqrMagnitude);
 }
コード例 #13
0
 public float GetDistanceBetweenCenters(Sphere3D sphere)
 {
     return((_center - sphere.Center).magnitude);
 }
コード例 #14
0
 public Sphere3D(Sphere3D source)
 {
     _radius = source._radius;
     _center = source._center;
 }
コード例 #15
0
 public bool FullyOverlaps(Sphere3D sphere)
 {
     return(GetDistanceBetweenCenters(sphere) + sphere.Radius <= _radius);
 }