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); } } }