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 bool TerrainLoaded(UnityEngine.Terrain setting, float detailDistance) { var data = setting.terrainData; var detailResolution = data.detailResolution; var heightMapResolution = data.heightmapResolution; var prototypes = data.detailPrototypes; var detailCount = prototypes.Length; var division = Mathf.CeilToInt(detailResolution / (float)_detailNodeSize); if (!Helper.AlmostEqual(detailResolution, division * _detailNodeSize)) { return(false); } var detailData = new List <int[, ]>(); if (_instancingDraw == null) { _instancingDraw = new DetailInstancingDraw[detailCount]; } List <DividedDetailProperty> detailProps = new List <DividedDetailProperty>(); for (int i = 0; i < detailCount; ++i) { detailData.Add(data.GetDetailLayer(0, 0, detailResolution, detailResolution, 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(data.GetHeights(0, 0, heightMapResolution, heightMapResolution), data.size.y); cluster.TerrainName = setting.name; _data.SetGridParam(data.size.x, detailDistance, nodeSize); _terrainProperty = new TerrainProperty(setting, data, detailDistance); for (int x = 0; x < division; ++x) { for (int z = 0; z < division; ++z) { var node = new GpuInstancingDetailNode(); node.TerrainName = setting.name; node.X = x; node.Z = z; node.SetInstantiationShader(_instantiationShader); node.SetShaderProperty(_terrainProperty, detailProps); node.InitCountInUnit(detailData, x, z, _detailNodeSize); cluster.AddNode(x, z, node); cluster.UpdateMaxCountInLayer(node); } } _data.AddCluster(cluster); return(true); }
public bool TerrainLoaded(UnityEngine.Terrain setting, float detailDistance, Vector3 basePos, float[,] heightMap) { var data = setting.terrainData; var detailResolution = data.detailResolution; var prototypes = data.detailPrototypes; var detailCount = prototypes.Length; var division = Mathf.CeilToInt(detailResolution / (float)_nodeSize); if (!Helper.AlmostEqual(detailResolution, division * _nodeSize)) { _logger.WarnFormat("unmatch param in detail: detailResolution -> {0}, unitSize -> {1}, division -> {2}", detailResolution, _nodeSize, division); return(false); } if (detailCount == 0) { _logger.Warn("no grass prototypes exists"); return(false); } var detailData = new List <int[, ]>(); if (_instancingDraw == null) { _instancingDraw = new DetailInstancingDraw[detailCount]; } List <DividedDetailProperty> detailProps = new List <DividedDetailProperty>(); float nodeMargin = float.MinValue; for (int i = 0; i < detailCount; ++i) { detailData.Add(data.GetDetailLayer(0, 0, detailResolution, detailResolution, 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); } } 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(heightMap, data.size.y, nodeMargin); cluster.TerrainName = setting.name; _data.SetGridParam(data.size.x, detailDistance, nodeSize); _terrainProperty = new TerrainProperty(); _terrainProperty.InitForDetail(setting, data, detailDistance, basePos); for (int x = 0; x < division; ++x) { for (int z = 0; z < division; ++z) { var node = new GpuInstancingDetailNode(); node.TerrainName = setting.name; node.X = x; node.Z = z; node.SetInstantiationShader(_instantiationShader); node.SetShaderProperty(_terrainProperty, detailProps); node.InitCountInUnit(detailData, x, z, _nodeSize); cluster.AddNode(x, z, node); cluster.UpdateMaxCountInLayer(node); } } _data.AddCluster(cluster); return(true); }
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); }