Exemple #1
0
 private void HandleHeightBuffer(Vector3 viewPoint)
 {
     if (viewPoint.x >= _minVisiblePos.x && viewPoint.x <= _maxVisiblePos.x &&
         viewPoint.z >= _minVisiblePos.y && viewPoint.z <= _maxVisiblePos.y)
     {
         if (_heightMapBuffer == null)
         {
             if (_heightMapData != null)
             {
                 _heightMapBuffer = new ComputeBuffer((_heightMapData.Length + 1) / 2, Constants.StrideSizeUint);
                 _heightMapBuffer.SetData(_heightMapData);
             }
             else
             {
                 _heightMapBuffer = new ComputeBuffer((_compactHeightMapDataLength + 3) / 4, Constants.StrideSizeUint);
                 IntPtr p = new IntPtr(_compactHeightMapData.GetBytesIntPtr().ToInt64() + _compactHeightMapDataStart);
                 _heightMapBuffer.SetDataWithIntPtr(p, _compactHeightMapDataLength);
             }
         }
     }
     else if (viewPoint.x < _minVisiblePos.x - Constants.DetailDisableBufferLength ||
              viewPoint.x > _maxVisiblePos.x + Constants.DetailDisableBufferLength ||
              viewPoint.z < _minVisiblePos.y - Constants.DetailDisableBufferLength ||
              viewPoint.z > _maxVisiblePos.y + Constants.DetailDisableBufferLength)
     {
         if (_heightMapBuffer != null)
         {
             _heightMapBuffer.Release();
             _heightMapBuffer = null;
         }
     }
 }
Exemple #2
0
        public void InitCountInUnit(int indexX, int indexY, int resolution, TextAsset rawData, List <int> maxCountInLayer,
                                    int rawDataOffset, int layerOffset, int division)
        {
            _resolution = resolution;
            _index      = new[] { indexX, indexY };

            var count = maxCountInLayer.Count;

            _totalCountInLayer = new int[count];

            _compactCountInNode = new OfflineDetailData
            {
                WholeData    = rawData,
                StartIndices = new List <int>(count),
                Lengths      = new List <int>(count)
            };

            var unitDataLength        = _resolution * _resolution * 2;
            var unitDataOffsetInLayer = (unitDataLength + 2) * (indexY * division + indexX);

            var index = rawDataOffset + unitDataOffsetInLayer;

            _transform  = new ComputeBuffer[count];
            _normal     = new ComputeBuffer[count];
            _color      = new ComputeBuffer[count];
            _count      = new ComputeBuffer[count];
            _countInCpu = new int[count];

            for (int i = 0; i < count; ++i)
            {
                if (maxCountInLayer[i] != 0)
                {
                    unsafe
                    {
                        var     head = new IntPtr(rawData.GetBytesIntPtr().ToInt64() + index);
                        ushort *data = (ushort *)head.ToPointer();

                        _totalCountInLayer[i] = *data;
                        _compactCountInNode.StartIndices.Add(index + 2);
                        _compactCountInNode.Lengths.Add(unitDataLength);
                    }
                    index += layerOffset;

                    _empty = false;
                }
                else
                {
                    _compactCountInNode.StartIndices.Add(0);
                    _compactCountInNode.Lengths.Add(0);
                    _totalCountInLayer[i] = 0;
                }

                _countInCpu[i] = 0;
            }
        }
Exemple #3
0
        private bool TerrainLoadedInternal(UnityEngine.Terrain setting, float treeDistance, Vector3 basePos,
                                           float[,] heightMap, TextAsset asset)
        {
            var data = setting.terrainData;

            var prototypes     = data.treePrototypes;
            var prototypeCount = prototypes.Length;

            if (prototypeCount == 0)
            {
                _logger.Warn("no tree prototypes exists");
                return(false);
            }

            var heightMapResolution = data.heightmapResolution;
            var division            = (heightMapResolution - 1) / _nodeSize;

            if (!Helper.AlmostEqual(heightMapResolution, division * _nodeSize + 1))
            {
                _logger.WarnFormat("unmatch param in tree: heightMapResolution -> {0}, nodeSize -> {1}, division -> {2}",
                                   heightMapResolution, _nodeSize, division);
                return(false);
            }

            var allTrees   = data.treeInstances;
            var treeCount  = allTrees.Length;
            var nodeMargin = float.MinValue;

            if (_instancingDraw == null)
            {
                _instancingDraw = new TreeInstancingDraw[prototypeCount];
            }

            for (int i = 0; i < prototypeCount; ++i)
            {
                if (_instancingDraw[i] == null)
                {
                    var renderer = new InstancingRenderer(prototypes[i].prefab);
                    nodeMargin         = Mathf.Max(nodeMargin, renderer.SphereRadius);
                    _instancingDraw[i] = new TreeInstancingDraw(renderer, VisibilityShader);
                }
                else
                {
                    nodeMargin = Mathf.Max(nodeMargin, _instancingDraw[i].RendererSphereRadius);
                }
            }

            var nodeSize = new Vector2(data.size.x / division, data.size.z / division);

            _data.SetGridParam(data.size.x, treeDistance, nodeSize);

            var cluster = new GpuInstancingNodeCluster <GpuInstancingTreeNode>();

            cluster.InitDivision(basePos, nodeSize, division, division, treeDistance);
            if (heightMap != null)
            {
                cluster.InitHeightMap(heightMap, data.size.y, nodeMargin);
            }
            else
            {
                // ignore version
                int dataIndex = 6;
                unsafe
                {
                    var     head        = new IntPtr(asset.GetBytesIntPtr().ToInt64() + dataIndex);
                    ushort *flowData    = (ushort *)head.ToPointer();
                    var     detailCount = *flowData;
                    dataIndex += 2 * (1 + detailCount);
                }

                cluster.InitHeightMap(asset, dataIndex, data.size.y, heightMapResolution, nodeMargin);
            }
            cluster.TerrainName = setting.name;

            _terrainProperty = new TerrainProperty();
            _terrainProperty.InitForTree(setting, data, treeDistance, basePos);

            var treeIndex           = new List <int> [division, division][];
            var maxIndex            = division - 1;
            var maxCountInPrototype = new List <int>(prototypeCount);
            var dummy = new List <int> [prototypeCount];

            for (int i = 0; i < prototypeCount; ++i)
            {
                maxCountInPrototype.Add(0);
                dummy[i] = new List <int>();
            }

            for (int i = 0; i < treeCount; ++i)
            {
                var tree = allTrees[i];
                var x    = Mathf.Min(Mathf.FloorToInt(tree.position.x * division), maxIndex);
                var z    = Mathf.Min(Mathf.FloorToInt(tree.position.z * division), maxIndex);

                if (treeIndex[x, z] == null)
                {
                    treeIndex[x, z] = new List <int> [prototypeCount];
                }

                if (treeIndex[x, z][tree.prototypeIndex] == null)
                {
                    treeIndex[x, z][tree.prototypeIndex] = new List <int>();
                }

                treeIndex[x, z][tree.prototypeIndex].Add(i);

                maxCountInPrototype[tree.prototypeIndex] = Mathf.Max(maxCountInPrototype[tree.prototypeIndex], treeIndex[x, z][tree.prototypeIndex].Count);
            }

            for (int x = 0; x < division; ++x)
            {
                for (int z = 0; z < division; ++z)
                {
                    var node = new GpuInstancingTreeNode
                    {
                        TerrainName = setting.name,
                        X           = x,
                        Z           = z
                    };

                    node.SetTreeInstances(treeIndex[x, z] ?? dummy, allTrees);
                    node.SetInstantiationShader(_instantiationShader);
                    node.SetShaderProperty(_terrainProperty);

                    cluster.AddNode(x, z, node);
                }
            }

            cluster.SetMaxCountInLayer(maxCountInPrototype);

            _data.AddCluster(cluster);
            return(true);
        }
Exemple #4
0
        public void InitHeightMap(TextAsset flowData, int start, float fullHeight, int resolution)
        {
            _compactHeightMapData       = flowData;
            _compactHeightMapDataStart  = start;
            _compactHeightMapDataLength = resolution * resolution * 2;

            if (_heightMinsU == null)
            {
                _heightMinsU = new ushort[_xCount, _zCount];
                _heightMaxsU = new ushort[_xCount, _zCount];
            }

            if (_heightMinsF == null)
            {
                _heightMinsF = new float[_xCount, _zCount];
                _heightMaxsF = new float[_xCount, _zCount];
            }

            for (int i = 0; i < _xCount; ++i)
            {
                for (int j = 0; j < _zCount; ++j)
                {
                    _heightMinsU[i, j] = ushort.MaxValue;
                    _heightMaxsU[i, j] = ushort.MinValue;
                }
            }

            var heightMapXCount = resolution;
            var heightMapZCount = resolution;
            var xPixelsPerUnit  = heightMapXCount / (float)_xCount;
            var zPixelsPerUnit  = heightMapZCount / (float)_zCount;

            while (Mathf.FloorToInt((heightMapXCount - 1) / xPixelsPerUnit) >= _xCount)
            {
                --heightMapXCount;
            }

            while (Mathf.FloorToInt((heightMapZCount - 1) / zPixelsPerUnit) >= _zCount)
            {
                --heightMapZCount;
            }

            unsafe
            {
                var     head = new IntPtr(_compactHeightMapData.GetBytesIntPtr().ToInt64() + start);
                ushort *data = (ushort *)head.ToPointer();

                for (int i = 0; i < heightMapZCount; ++i)
                {
                    for (int j = 0; j < heightMapXCount; ++j)
                    {
                        var height = *data;
                        data += 1;

                        var x = Mathf.FloorToInt(j / xPixelsPerUnit);
                        var z = Mathf.FloorToInt(i / zPixelsPerUnit);

                        _heightMinsU[x, z] = (ushort)Mathf.Min(_heightMinsU[x, z], height);
                        _heightMaxsU[x, z] = (ushort)Mathf.Max(_heightMaxsU[x, z], height);
                    }
                }
            }

            var coefficient = fullHeight / MaxHeightInUshort;

            for (int i = 0; i < _xCount; ++i)
            {
                for (int j = 0; j < _zCount; ++j)
                {
                    _heightMinsF[i, j] = _heightMinsU[i, j] * coefficient;
                    _heightMaxsF[i, j] = _heightMaxsU[i, j] * coefficient;
                }
            }

            BuildAabb(_heightMinsF, _heightMaxsF);
        }
        public bool TerrainLoaded(TextAsset asset, UnityEngine.Terrain setting, float detailDistance)
        {
            var data = setting.terrainData;
            // ignore version
            int dataIndex = 2;

            int        heightMapResolution = 0;
            int        detailResolution    = 0;
            int        detailCount         = 0;
            List <int> maxCountInLayer     = new List <int>();

            unsafe
            {
                var     head     = new IntPtr(asset.GetBytesIntPtr().ToInt64() + dataIndex);
                ushort *flowData = (ushort *)head.ToPointer();

                heightMapResolution = *flowData++;
                detailResolution    = *flowData++;
                _detailNodeSize     = *flowData++;
                detailCount         = *flowData++;
                for (int i = 0; i < detailCount; ++i)
                {
                    maxCountInLayer.Add(*flowData++);
                }

                dataIndex += 2 * (4 + detailCount);
            }

            var division   = detailResolution / _detailNodeSize;
            var prototypes = data.detailPrototypes;

            if (heightMapResolution != data.heightmapResolution || detailResolution != data.detailResolution ||
                detailCount != prototypes.Length)
            {
                return(false);
            }

            if (_instancingDraw == null)
            {
                _instancingDraw = new DetailInstancingDraw[detailCount];
            }

            List <DividedDetailProperty> detailProps = new List <DividedDetailProperty>();

            for (int i = 0; i < detailCount; ++i)
            {
                detailProps.Add(new DividedDetailProperty(data, prototypes[i], _detailNodeSize, i));

                if (_instancingDraw[i] == null)
                {
                    var renderer = new InstancingRenderer(prototypes[i]);
                    _instancingDraw[i] = new DetailInstancingDraw(renderer, VisibilityShader, setting, data);
                }
            }

            var nodeSize = new Vector2(data.size.x / division, data.size.z / division);

            var cluster = new GpuInstancingNodeCluster <GpuInstancingDetailNode>();

            cluster.InitDivision(setting.transform.position, nodeSize, division, division, detailDistance);
            cluster.InitHeightMap(asset, dataIndex, data.size.y, heightMapResolution);

            cluster.TerrainName = setting.name;

            dataIndex += heightMapResolution * heightMapResolution * 2;

            _data.SetGridParam(data.size.x, detailDistance, nodeSize);

            _terrainProperty = new TerrainProperty(setting, data, detailDistance);
            var layerLength = (detailResolution * detailResolution + division * division) * 2;

            for (int z = 0; z < division; ++z)
            {
                for (int x = 0; x < division; ++x)
                {
                    var node = new GpuInstancingDetailNode();

                    node.TerrainName = setting.name;
                    node.X           = x;
                    node.Z           = z;

                    node.SetInstantiationShader(_instantiationShader);
                    node.SetShaderProperty(_terrainProperty, detailProps);
                    node.InitCountInUnit(x, z, _detailNodeSize, asset, maxCountInLayer, dataIndex, layerLength, division);

                    cluster.AddNode(x, z, node);
                }
            }

            cluster.SetMaxCountInLayer(maxCountInLayer);

            _data.AddCluster(cluster);
            return(true);
        }
        public bool TerrainLoaded(TextAsset asset, UnityEngine.Terrain setting, float detailDistance, Vector3 basePos)
        {
            var data = setting.terrainData;
            // ignore version
            int dataIndex = 2;

            int        heightMapResolution = 0;
            int        detailResolution    = 0;
            int        detailCount         = 0;
            List <int> maxCountInLayer     = new List <int>();

            unsafe
            {
                var     head     = new IntPtr(asset.GetBytesIntPtr().ToInt64() + dataIndex);
                ushort *flowData = (ushort *)head.ToPointer();

                heightMapResolution = *flowData++;
                detailResolution    = *flowData++;
                _nodeSize           = *flowData++;
                detailCount         = *flowData++;
                for (int i = 0; i < detailCount; ++i)
                {
                    maxCountInLayer.Add(*flowData++);
                }

                dataIndex += 2 * (4 + detailCount);
            }

            var division   = detailResolution / _nodeSize;
            var prototypes = data.detailPrototypes;

            if (heightMapResolution != data.heightmapResolution || detailResolution != data.detailResolution ||
                detailCount != prototypes.Length)
            {
                _logger.WarnFormat("unmatch param in detail: heightMapResolution -> {0}:{1}, detailResolution -> {2}:{3}, detailCount -> {4}:{5}",
                                   data.heightmapResolution, heightMapResolution, data.detailResolution, detailResolution, prototypes.Length, detailCount);
                return(false);
            }

            if (detailCount == 0)
            {
                _logger.Error("no grass prototypes exists");
                return(false);
            }

            if (_instancingDraw == null)
            {
                _instancingDraw = new DetailInstancingDraw[detailCount];
            }

            if (detailCount != _instancingDraw.Length)
            {
                _logger.ErrorFormat("unmatch grass count: unique->{0} other->{1}", detailCount, _instancingDraw);
                return(false);
            }

            List <DividedDetailProperty> detailProps = new List <DividedDetailProperty>();
            float nodeMargin = float.MinValue;

            for (int i = 0; i < detailCount; ++i)
            {
                detailProps.Add(new DividedDetailProperty(prototypes[i], _nodeSize, i));

                if (_instancingDraw[i] == null)
                {
                    var renderer = new InstancingRenderer(prototypes[i]);
                    nodeMargin         = Mathf.Max(nodeMargin, renderer.SphereRadius);
                    _instancingDraw[i] = new DetailInstancingDraw(renderer, VisibilityShader, SortShader, setting, data, basePos);
                }
                else
                {
                    nodeMargin = Mathf.Max(nodeMargin, _instancingDraw[i].RendererSphereRadius);
                }
            }

            var nodeSize = new Vector2(data.size.x / division, data.size.z / division);

            var cluster = new GpuInstancingNodeCluster <GpuInstancingDetailNode>();

            cluster.InitDivision(basePos, nodeSize, division, division, detailDistance);
            cluster.InitHeightMap(asset, dataIndex, data.size.y, heightMapResolution, nodeMargin);

            cluster.TerrainName = setting.name;

            dataIndex += heightMapResolution * heightMapResolution * 2;

            _data.SetGridParam(data.size.x, detailDistance, nodeSize);

            _terrainProperty = new TerrainProperty();
            _terrainProperty.InitForDetail(setting, data, detailDistance, basePos);

            var layerLength = (detailResolution * detailResolution + division * division) * 2;

            for (int z = 0; z < division; ++z)
            {
                for (int x = 0; x < division; ++x)
                {
                    var node = new GpuInstancingDetailNode();

                    node.TerrainName = setting.name;
                    node.X           = x;
                    node.Z           = z;

                    node.SetInstantiationShader(_instantiationShader);
                    node.SetShaderProperty(_terrainProperty, detailProps);
                    node.InitCountInUnit(x, z, _nodeSize, asset, maxCountInLayer, dataIndex, layerLength, division);

                    cluster.AddNode(x, z, node);
                }
            }

            cluster.SetMaxCountInLayer(maxCountInLayer);

            _data.AddCluster(cluster);
            return(true);
        }