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