示例#1
0
        /// <summary>
        /// Gives the current camera data to the traversal thread and updates the GameObjects. Called from the MainThread. As described in the Bachelor Thesis in chapter 3.1.3 "Main Thread"
        /// </summary>
        public void Update()
        {
            unityThread = Thread.CurrentThread;
            if (paused)
            {
                return;
            }
            //Set new Camera Data
            traversalThread.SetNextCameraData(camera.transform.position, camera.transform.forward, GeometryUtility.CalculateFrustumPlanes(camera), camera.pixelRect.height, camera.fieldOfView);

            //Update GameObjects
            Queue <Node> toRender;
            Queue <Node> toDelete;

            lock (locker) {
                toRender      = this.toRender;
                toDelete      = this.toDelete;
                this.toRender = null;
                this.toDelete = null;
            }
            if (toRender == null)
            {
                return;
            }
            while (toDelete.Count != 0)
            {
                Node n = toDelete.Dequeue();
                lock (n) {
                    if (n.HasGameObjects())
                    {
                        n.RemoveGameObjects(config);
                        cache.Insert(n);
                    }
                }
            }
            while (toRender.Count != 0)
            {
                Node n = toRender.Dequeue();
                lock (n) {
                    if (n.HasPointsToRender() && (n.Parent == null || n.Parent.HasGameObjects()))
                    {
                        n.CreateGameObjects(config);
                    }
                }
            }
            Monitor.Enter(toDeleteExternal);
            while (toDeleteExternal.Count != 0)
            {
                Node rootNode = toDeleteExternal.Dequeue();
                rootNodes.Remove(rootNode);
                Queue <Node> toRemove = new Queue <Node>();
                toRemove.Enqueue(rootNode);
                while (toRemove.Count != 0)
                {
                    Node n = toRemove.Dequeue();
                    cache.Withdraw(n);
                    if (n.HasGameObjects())
                    {
                        n.RemoveGameObjects(config);
                    }
                    if (n.HasPointsToRender())
                    {
                        n.ForgetPoints();
                        foreach (Node child in n)
                        {
                            toRemove.Enqueue(child);
                        }
                    }
                }
            }
            Monitor.Exit(toDeleteExternal);

            //Notify Traversal Thread
            lock (traversalThread) {
                Monitor.PulseAll(traversalThread);
            }
        }
示例#2
0
        private uint TraverseAndBuildRenderingQueue()
        {
            //Camera Data
            Vector3 cameraPosition;
            Vector3 camForward;

            Plane[] frustum;
            float   screenHeight;
            float   fieldOfView;

            PriorityQueue <double, Node> toProcess = new HeapPriorityQueue <double, Node>();

            lock (locker) {
                if (this.frustum == null)
                {
                    return(0);
                }
                cameraPosition = this.cameraPosition;
                camForward     = this.camForward;
                frustum        = this.frustum;
                screenHeight   = this.screenHeight;
                fieldOfView    = this.fieldOfView;
            }
            //Clearing Queues
            uint           renderingpointcount = 0;
            uint           maxnodestoload      = nodesLoadedPerFrame;
            uint           maxnodestorender    = nodesGOsPerFrame;
            HashSet <Node> newVisibleNodes     = new HashSet <Node>();

            foreach (Node rootNode in rootNodes)
            {
                Vector3 center        = rootNode.BoundingBox.GetBoundsObject().center;
                double  distance      = (center - cameraPosition).magnitude;
                double  slope         = Math.Tan(fieldOfView / 2 * Mathf.Deg2Rad);
                double  projectedSize = (screenHeight / 2.0) * rootNode.BoundingBox.Radius() / (slope * distance);
                if (projectedSize > minNodeSize)
                {
                    Vector3 camToNodeCenterDir = (center - cameraPosition).normalized;
                    double  angle       = Math.Acos(camForward.x * camToNodeCenterDir.x + camForward.y * camToNodeCenterDir.y + camForward.z * camToNodeCenterDir.z);
                    double  angleWeight = Math.Abs(angle) + 1.0; //+1, to prevent divsion by zero
                    double  priority    = projectedSize / angleWeight;
                    toProcess.Enqueue(rootNode, priority);
                }
                else
                {
                    DeleteNode(rootNode);
                }
            }

            while (!toProcess.IsEmpty() && running)
            {
                Node n = toProcess.Dequeue(); //Min Node Size was already checked

                //Is Node inside frustum?
                if (Util.InsideFrustum(n.BoundingBox, frustum))
                {
                    bool loadchildren = false;
                    lock (n) {
                        if (n.PointCount == -1)
                        {
                            if (maxnodestoload > 0)
                            {
                                loadingThread.ScheduleForLoading(n);
                                --maxnodestoload;
                                loadchildren = true;
                            }
                        }
                        else if (renderingpointcount + n.PointCount <= pointBudget)
                        {
                            if (n.HasGameObjects())
                            {
                                renderingpointcount += (uint)n.PointCount;
                                visibleNodes.Remove(n);
                                newVisibleNodes.Add(n);
                                loadchildren = true;
                            }
                            else if (n.HasPointsToRender())
                            {
                                //Might be in Cache -> Withdraw
                                if (maxnodestorender > 0)
                                {
                                    cache.Withdraw(n);
                                    renderingpointcount += (uint)n.PointCount;
                                    toRender.Enqueue(n);
                                    --maxnodestorender;
                                    newVisibleNodes.Add(n);
                                    loadchildren = true;
                                }
                            }
                            else
                            {
                                if (maxnodestoload > 0)
                                {
                                    loadingThread.ScheduleForLoading(n);
                                    --maxnodestoload;
                                    loadchildren = true;
                                }
                            }
                        }
                        else
                        {
                            maxnodestoload   = 0;
                            maxnodestorender = 0;
                            if (n.HasGameObjects())
                            {
                                visibleNodes.Remove(n);
                                DeleteNode(n);
                            }
                        }
                    }

                    if (loadchildren)
                    {
                        foreach (Node child in n)
                        {
                            Vector3 center        = child.BoundingBox.GetBoundsObject().center;
                            double  distance      = (center - cameraPosition).magnitude;
                            double  slope         = Math.Tan(fieldOfView / 2 * Mathf.Deg2Rad);
                            double  projectedSize = (screenHeight / 2.0) * child.BoundingBox.Radius() / (slope * distance);
                            if (projectedSize > minNodeSize)
                            {
                                Vector3 camToNodeCenterDir = (center - cameraPosition).normalized;
                                double  angle       = Math.Acos(camForward.x * camToNodeCenterDir.x + camForward.y * camToNodeCenterDir.y + camForward.z * camToNodeCenterDir.z);
                                double  angleWeight = Math.Abs(angle) + 1.0; //+1, to prevent divsion by zero
                                double  priority    = projectedSize / angleWeight;
                                toProcess.Enqueue(child, priority);
                            }
                            else
                            {
                                DeleteNode(child);
                            }
                        }
                    }
                }
                else
                {
                    //This node or its children might be visible
                    DeleteNode(n);
                }
            }
            foreach (Node n in visibleNodes)
            {
                DeleteNode(n);
            }
            visibleNodes = newVisibleNodes;
            return(renderingpointcount);
        }