Пример #1
0
 public void AddNode(int x, int z, T node)
 {
     _nodeStatuses[x, z] = new NodeIndicator(this, _aabbMins[x, z], _aabbMaxs[x, z])
     {
         Node = node
     };
 }
        public void CreateUnitedInstance(InstancingDraw[] instancingData)
        {
            if (instancingData[0].State == InstancingDrawState.NotInitialized || _newInstanceCountLimit)
            {
                var dataLength = instancingData.Length;
                for (int i = 0; i < dataLength; ++i)
                {
                    instancingData[i].SetInstancingCount(_cachedNodes.Length, _maxInstanceCountPerRenderInUnit[i]);
                }
            }

            if (_previousInstantiatingNode != null)
            {
                if (_previousInstantiatingNode.IsDuringInstantiation)
                {
                    _previousInstantiatingNode.SetInstantiated();
                    var count = _cachedNodes.Length;
                    var index = 0;
                    for (; index < count; ++index)
                    {
                        if (_cachedNodes[index] == null)
                        {
                            _cachedNodes[index] = _previousInstantiatingNode;
                            break;
                        }
                    }

                    if (index == count)
                    {
                        logger.InfoFormat("Full Exception, mins: {0}, maxs: {1}",
                                          _previousInstantiatingNode.Mins.ToStringExt(), _previousInstantiatingNode.Maxs.ToStringExt());
                    }

                    if (!_newInstanceCountLimit)
                    {
                        ReplaceBuffer(_previousInstantiatingNode.Node, index, instancingData);
                    }
                }
                else
                {
                    _previousInstantiatingNode.Node.ReleaseBuffer();
                }

                _previousInstantiatingNode = null;
            }

            if (_newInstanceCountLimit)
            {
                var count = _cachedNodes.Length;
                for (int i = 0; i < count; ++i)
                {
                    if (_cachedNodes[i] != null)
                    {
                        ReplaceBuffer(_cachedNodes[i].Node, i, instancingData);
                    }
                }

                _newInstanceCountLimit = false;
            }

            if (_curInstantiatingNode != null)
            {
                _previousInstantiatingNode = _curInstantiatingNode;
                _curInstantiatingNode      = null;
            }

            var drawCount = instancingData.Length;

            for (int i = 0; i < drawCount; ++i)
            {
                if (instancingData[i].State == InstancingDrawState.Enable)
                {
                    instancingData[i].ClearRealBlockCount();

                    var count = _cachedNodes.Length;
                    for (int j = 0; j < count; ++j)
                    {
                        var node = _cachedNodes[j];
                        if (node != null)
                        {
                            if (node.IsOutOfRange)
                            {
                                _cachedNodes[j] = null;
                                continue;
                            }

                            if (node.IsActive)
                            {
                                var realCount = node.Node.GetInstancingDataCount(i);
                                instancingData[i].SetRealBlockCount(j, realCount);
                            }
                        }
                    }
                }
            }
        }
        public void DistanceAndFrustumCulling(CameraFrustum frustum)
        {
            var viewPoint = frustum.ViewPoint;
            var halfSize  = _clusterDimensions / 2;

            var minVisiblePosX = viewPoint.x - _cullingDistance;
            var minVisiblePosZ = viewPoint.z - _cullingDistance;
            var maxVisiblePosX = minVisiblePosX + _cullingDistance * 2;
            var maxVisiblePosZ = minVisiblePosZ + _cullingDistance * 2;

            int curVisibleStartX = Mathf.FloorToInt(minVisiblePosX / _clusterSize) + halfSize;
            int curVisibleStartZ = Mathf.FloorToInt(minVisiblePosZ / _clusterSize) + halfSize;
            int curVisibleEndX   = Mathf.CeilToInt(maxVisiblePosX / _clusterSize) + halfSize;
            int curVisibleEndZ   = Mathf.CeilToInt(maxVisiblePosZ / _clusterSize) + halfSize;

            bool enoughRoom = true;

            for (int i = _lastVisibleStartX; i < _lastVisibleEndX; ++i)
            {
                for (int j = _lastVisibleStartZ; j < _lastVisibleEndZ; ++j)
                {
                    if (i >= 0 && i < _clusterDimensions && j >= 0 && j < _clusterDimensions)
                    {
                        var cluster = _nodeClusters[i, j];
                        if (cluster == null)
                        {
                            continue;
                        }

                        var node = cluster.DistanceAndFrustumCulling(viewPoint, enoughRoom);
                        if (node != null && enoughRoom)
                        {
                            _curInstantiatingNode = node;
                            enoughRoom            = false;
                        }
                    }
                }
            }

            if (_lastVisibleStartX != curVisibleStartX || _lastVisibleEndX != curVisibleEndX ||
                _lastVisibleStartZ != curVisibleStartZ || _lastVisibleEndZ != curVisibleEndZ)
            {
                for (int i = curVisibleStartX; i < curVisibleEndX; ++i)
                {
                    for (int j = curVisibleStartZ; j < curVisibleEndZ; ++j)
                    {
                        if (i >= 0 && i < _clusterDimensions && j >= 0 && j < _clusterDimensions)
                        {
                            var cluster = _nodeClusters[i, j];
                            if (cluster == null)
                            {
                                continue;
                            }

                            var node = cluster.DistanceAndFrustumCulling(viewPoint, enoughRoom);
                            if (node != null && enoughRoom)
                            {
                                _curInstantiatingNode = node;
                                enoughRoom            = false;
                            }
                        }
                    }
                }

                _lastVisibleStartX = curVisibleStartX;
                _lastVisibleEndX   = curVisibleEndX;
                _lastVisibleStartZ = curVisibleStartZ;
                _lastVisibleEndZ   = curVisibleEndZ;
            }

            if (!enoughRoom)
            {
                _curInstantiatingNode.SetInstantiating();
                _curInstantiatingNode.Node.BuildBuffer(_curInstantiatingNode.HeightBuffer());
            }

            var count = _cachedNodes.Length;

            for (int i = 0; i < count; ++i)
            {
                var node = _cachedNodes[i];
                if (node != null && node.IsInstantiated)
                {
                    node.IsActive = frustum.IsDetailNodeVisible(node.Mins, node.Maxs);
                }
            }
        }