Beispiel #1
0
        /// <summary>
        /// 解析地形Tile数据
        /// </summary>
        /// <param name="iSaveDir">保存目录</param>
        /// <param name="iTileIndex">Tile横向索引(Z轴方向)</param>
        /// <param name="iTerrainObj">拆分用地形对象</param>
        /// <param name="iMaxLayerLevel">地形最大层级</param>
        /// <param name="iLayerIndex">层级索引</param>
        /// <param name="iUpdateProgress">进度更新委托</param>
        public void SplitTerrains(
            string iSaveDir, GameObject iTerrainObj,
            Vector2 iTileIndex, int iMaxLayerLevel, int iLayerIndex,
            ProgressBarUpdate iUpdateProgress = null)
        {
            // 计算当前层级的拆分数量
            var slicingCount = TerrainsSettings.CurSlicingCount(iMaxLayerLevel, iLayerIndex);

            // 计算当前层级Chunk尺寸计算
            for (var r = 0; r < slicingCount; ++r)
            {
                for (var c = 0; c < slicingCount; ++c)
                {
                    // 开始拆分
                    SplitTerrains(
                        iSaveDir, iMaxLayerLevel - iLayerIndex, iTileIndex, slicingCount,
                        iTerrainObj, new Vector2(r, c), iUpdateProgress);
                }
            }
        }
Beispiel #2
0
        /// <summary>
        /// 拆分地形
        /// </summary>
        /// <param name="iSaveDir">保存路径</param>
        /// <param name="iLayerLevel">地形层级</param>
        /// <param name="iTileIndex">地形的Tile索引</param>
        /// <param name="iSlicingCount">单个地形的拆分个数。(如:2x2 则为2)</param>
        /// <param name="iTerrainObj">地形对象</param>
        /// <param name="iChunkTileIndex">单个地形的拆分成chunk后的tile索引</param>
        /// <param name="iUpdateProgress">进度更新委托</param>
        private void SplitTerrains(
            string iSaveDir, int iLayerLevel,
            Vector2 iTileIndex, int iSlicingCount,
            GameObject iTerrainObj, Vector2 iChunkTileIndex,
            ProgressBarUpdate iUpdateProgress = null)
        {
            if (string.IsNullOrEmpty(iSaveDir))
            {
                return;
            }
            if (0 >= iSlicingCount)
            {
                return;
            }
            if (null == iTerrainObj)
            {
                Error("SplitTerrains():The gameobject is null or invalid in hierarchy!!!");
                return;
            }

            var terrain = iTerrainObj.GetComponent <Terrain>();

            if (null == terrain)
            {
                Error("SplitTerrains():There is no component named terrain in the gameobject(name:{0})!!!",
                      iTerrainObj.name);
                return;
            }

            // 地形数据
            var terrainData = terrain.terrainData;

            // 地形尺寸
            var terrainSize = terrainData.size;

            // 得到地图分辨率
            var newHeightmapResolution = (terrainData.heightmapResolution - 1) / iSlicingCount;
            var newAlphamapResolution  = terrainData.alphamapResolution / iSlicingCount;
            var newbaseMapResolution   = terrainData.baseMapResolution / iSlicingCount;
            // 溅斑原型列表
            var splatProtos = terrainData.splatPrototypes;

            var x = (int)iChunkTileIndex.x;
            var y = (int)iChunkTileIndex.y;

            //创建资源
            // 地形拆分chunk保存路径
            var morton    = TerrainsSettings.Morton(iTileIndex, iChunkTileIndex, iSlicingCount, iLayerLevel);
            var chunkName = string.Format("{0}{1}.asset", TerrainsSettings.ChunkNamePrefix, morton);
            var savePath  = string.Format("{0}/{1}", iSaveDir, chunkName);

            // 更新进度 - 拆分开始
            if (null != iUpdateProgress)
            {
                var statusTxt = string.Format("拆分开始:{0}...", chunkName);
                iUpdateProgress(statusTxt, false);
            }
            var newData = new TerrainData();

            if (null == newData)
            {
                Error("SplitTerrains():Failed!!(SavePath:{0})",
                      savePath);
                return;
            }
            AssetDatabase.CreateAsset(newData, savePath);

            //设置分辨率参数
            newData.heightmapResolution = newHeightmapResolution;
            newData.alphamapResolution  = newAlphamapResolution;
            newData.baseMapResolution   = newbaseMapResolution;

            //设置大小
            newData.size = new Vector3(terrainSize.x / iSlicingCount, terrainSize.y, terrainSize.z / iSlicingCount);

            //设置地形原型
            var newSplats = new SplatPrototype[splatProtos.Length];

            for (var i = 0; i < splatProtos.Length; ++i)
            {
                newSplats[i] = new SplatPrototype
                {
                    texture = splatProtos[i].texture, tileSize = splatProtos[i].tileSize
                };

                var offsetX = (newData.size.x * x) % splatProtos[i].tileSize.x + splatProtos[i].tileOffset.x;
                var offsetY = (newData.size.z * y) % splatProtos[i].tileSize.y + splatProtos[i].tileOffset.y;
                newSplats[i].tileOffset = new Vector2(offsetX, offsetY);
            }
            newData.splatPrototypes = newSplats;

            //设置混合贴图
            var alphamap = new float[newAlphamapResolution, newAlphamapResolution, splatProtos.Length];

            alphamap = terrainData.GetAlphamaps(
                x * newData.alphamapWidth,
                y * newData.alphamapHeight,
                newData.alphamapWidth,
                newData.alphamapHeight);
            newData.SetAlphamaps(0, 0, alphamap);

            //设置高度
            var xBase  = (terrainData.heightmapWidth - 1) / iSlicingCount;
            var yBase  = (terrainData.heightmapHeight - 1) / iSlicingCount;
            var height = terrainData.GetHeights(xBase * x, yBase * y, xBase + 1, yBase + 1);

            newData.SetHeights(0, 0, height);
            AssetDatabase.SaveAssets();

            // 更新进度 - 拆分成功
            if (null != iUpdateProgress)
            {
                var statusTxt = string.Format("拆分成功:{0}", chunkName);
                iUpdateProgress(statusTxt, true);
            }
        }
Beispiel #3
0
        /// <summary>
        /// 拆分地形
        /// </summary>
        /// <param name="iLevel">层级(影响到左边缩进的余白)</param>
        private void SplitTerrains(int iLevel)
        {
            var level = iLevel;

            DrawMiddleGameObject(
                level, "地形根节点:", ref _terrainsRoot);
            var childCount = 0;

            if (!_terrainsRoot)
            {
                return;
            }
            childCount = _terrainsRoot.transform.childCount;
            // 若长宽地形个数不想等
            if (false == UtilsTools.IsSquare(childCount))
            {
                DrawLabel(level + 1, "地形部署长宽不相同(不是 N x N 布局)!", Color.red);
            }
            else
            {
                // 保存地形Tile尺寸
                if (Math.Abs(ConfData.TileSize.x * ConfData.TileSize.y - childCount) > 0.0f)
                {
                    ConfData.TileSize.x = (float)Math.Sqrt(childCount);
                    ConfData.TileSize.y = ConfData.TileSize.x;
                }

                DrawMiddleLabel(level, "chunk拆分数:");
                ++level;

                DrawLabel(level, "因为与到处高度图相关,拆分个数必须为2的N次幂(1~64)", Color.yellow);
                var lastSlicingCount = ConfData.chunkData.SlicingCount;
                DrawMiddleSlider(
                    level, "个数( N x N ):", ref lastSlicingCount,
                    1.0f, 64);
                if (!UtilsTools.IsPowerOf2((int)lastSlicingCount))
                {
                    var error = string.Format("{0} 不是2的N次幂(1~64)!",
                                              (int)ConfData.chunkData.SlicingCount);
                    DrawLabel(level + 1, error, Color.red);
                }
                else
                {
                    if (Math.Abs(lastSlicingCount - ConfData.chunkData.SlicingCount) > 0.0f)
                    {
                        // 有变化贼,晴空已有数据
                        Settings.Clear();
                        ConfData.chunkData.SlicingCount = lastSlicingCount;
                        // 清空Debug用绘制节点
                        ClearDebugNode();

                        // 层级预览信息清空
                        _layerPreviewTitles.Clear();
                        _layerPreviewSelected.Clear();
                    }

                    // 分界线
                    DrawLongLabel(0, "---------------");
                    DrawSingleLongToggle(level, "是否预览拆分边界:", _chunkBoundPreviewVisiable,
                                         delegate(bool iValue) { _chunkBoundPreviewVisiable = iValue; });
                    // 选择层级
                    // 取得最高层级
                    var maxLayerLevel = GetMaxLayerLevel((int)ConfData.chunkData.SlicingCount);
                    // 层级菜单标题
                    if (0 >= _layerPreviewSelected.Count)
                    {
                        for (var l = 0; l <= maxLayerLevel; ++l)
                        {
                            _layerPreviewTitles.Add(string.Format("层级{0}", l));
                            _layerPreviewSelected.Add(false);
                        }
                    }
                    if (_chunkBoundPreviewVisiable)
                    {
                        // 各层级显示
                        DrawLongLabel(level + 1, string.Format("当前拆分数可分 {0} 层:", maxLayerLevel + 1));
                        DrawMiddleMultiplyToggle(level + 2, _layerPreviewTitles.ToArray(), _layerPreviewSelected.ToArray(),
                                                 delegate(int l, bool iSelected) {
                            _layerPreviewSelected[l] = iSelected;
                            if (!iSelected)
                            {
                                ClearDebugNode(l);
                            }
                        });

                        // 显示颜色设定
                        var flg = false;
                        for (var l = 0; l <= maxLayerLevel; ++l)
                        {
                            if (!_layerPreviewSelected[l])
                            {
                                continue;
                            }
                            flg = true;
                        }

                        if (flg)
                        {
                            var layerPreview = ConfData.chunkData.Preview;
                            DrawLongLabel(level + 3, "颜色设定:");

                            DrawMiddleColor(level + 4, "边色", layerPreview.edgeColor,
                                            delegate(Color iColor)
                            {
                                layerPreview.edgeColor = iColor;
                                // 重置所有边的颜色
                                UtilsDraw.ResetAllCylinderColor(iColor,
                                                                (int)DrawType.TerrainChunkCylinder);
                            });

                            DrawMiddleColor(level + 4, "顶点色", layerPreview.vertexColor,
                                            delegate(Color iColor)
                            {
                                layerPreview.vertexColor = iColor;
                                // 重置所有边的颜色
                                UtilsDraw.ResetAllVertexColor(iColor,
                                                              (int)DrawType.TerrainChunkVertex);
                            });
                            DrawMiddleSlider(level + 4, "缩放",
                                             layerPreview.Scale, delegate(float iValue)
                            {
                                layerPreview.Scale = iValue;
                                UtilsDraw.ResetAllBoundsPreviewScale(
                                    iValue, (int)DrawType.TerrainChunkCylinder | (int)DrawType.TerrainChunkVertex);
                            },
                                             1.0f, 50.0f);
                            --level;
                        }

                        // 遍历根节点并取得包围盒
                        if (null == _terrainsRoot)
                        {
                            return;
                        }
                        // 基准原点:子节点中最小的点为为基准原点(既:最左最前的为第一块地形Tile)
                        // 其他的地形都以该地形位置准排布
                        var baseOriginPos = GetOriginPosOfTerrainsFromTiles(_terrainsRoot.transform);

                        var terrainTileSize = Vector3.zero;
                        for (var i = 0; i < _terrainsRoot.transform.childCount; ++i)
                        {
                            var child = _terrainsRoot.transform.GetChild(i);
                            if (null == child)
                            {
                                continue;
                            }
                            if (false == child.gameObject.activeInHierarchy)
                            {
                                continue;
                            }

                            // 地形Tile尺寸
                            if (Vector3.zero.Equals(terrainTileSize))
                            {
                                terrainTileSize = TerrainsSettings.GetTerrainSize(child.gameObject);
                            }

                            // Tile Index
                            var tileIndex = GetTerrainTileIndexByPos(
                                baseOriginPos, child.transform.position,
                                terrainTileSize);

                            // 按照层级生成解析用的地形层级数据
                            for (var layerIndex = 0; layerIndex <= maxLayerLevel; ++layerIndex)
                            {
                                // 当前层级的chunk尺寸
                                var layerChunkSize = TerrainsSettings.GetTerrainChunkSize(
                                    terrainTileSize, maxLayerLevel, layerIndex);

                                // 拆分当前层级的chunk数据
                                Settings.ParserTerrainTileData(
                                    tileIndex, layerChunkSize, maxLayerLevel,
                                    layerIndex);
                            }

                            for (var l = 0; l <= maxLayerLevel; ++l)
                            {
                                if (!_layerPreviewSelected[l])
                                {
                                    continue;
                                }
                                // 取得当前层级的chunk信息
                                var chunks = Settings.GetChunkData(l);
                                if (null == chunks || 0 >= chunks.Count)
                                {
                                    continue;
                                }
                                var bounds = new List <Bounds>();
                                // 以莫顿码为chunk索引
                                var chunksIndex = new List <int>();
                                foreach (var chunk in chunks)
                                {
                                    bounds.Add(chunk.Bounds);
                                    chunksIndex.Add((int)chunk.Morton);
                                }
                                // 绘制Chunks包围盒
                                var layerPreview = ConfData.chunkData.Preview;
                                if (null == layerPreview)
                                {
                                    continue;
                                }
                                UtilsDraw.DrawChunkBounds(
                                    bounds.ToArray(), chunksIndex.ToArray(),
                                    child.transform,
                                    layerPreview.edgeColor, layerPreview.vertexColor, layerPreview.Scale, l);
                            }
                        }
                        Settings.AutoSort();
                    }
                    else
                    {
                        ClearDebugNode();
                    }

                    DrawLongLabel(0, "---------------");

                    DrawLongLabel(0, "拆分设定:");
                    DrawLongLabel(1, "数据导入/导出目录:");
                    DrawLabel(2, string.Format("Chunk : {0}", Settings.ChunkDataDir), Color.green);
                    DrawLabel(2, string.Format("预制体 : {0}", Settings.PrefabsDataDir), Color.green);

                    DrawSingleMiddleToggle(1, "仅处理静态物体:", ConfData.chunkData.StaticOnly,
                                           delegate(bool iValue) { ConfData.chunkData.StaticOnly = iValue; });

                    // 地形导出层级
                    DrawSelectList(1, "地形导出层级:", _layerPreviewTitles.ToArray(), ref _exportLayerLevel);

                    // 预制体导出深度
                    DrawMiddleSlider(1, "预制体导出深度:",
                                     ConfData.chunkData.PrefabsExportDepthLimit,
                                     delegate(float iValue) { ConfData.chunkData.PrefabsExportDepthLimit = (int)iValue; },
                                     1.0f, 15.0f);

                    DrawSingleButton(0, "拆分场景",
                                     delegate()
                    {
                        // 显示处理进度条
                        ProgressBarStart("拆分地形", "开始拆分...");

                        // Chunk导出目录检测
                        var dirInfo = new DirectoryInfo(Settings.ChunkDataDir);
                        UtilsTools.CheckAndCreateDirByFullDir(dirInfo.FullName);

                        // 清空保存目录,但不删除目录本身
                        UtilsTools.ClearDirectory(TerrainsSettings.DataBaseDir, false);

                        // 遍历根节点并取得包围盒
                        if (null == _terrainsRoot)
                        {
                            return;
                        }
                        // 基准原点:子节点中最小的点为为基准原点(既:最左最前的为第一块地形Tile)
                        // 其他的地形都以该地形位置准排布
                        var baseOriginPos = GetOriginPosOfTerrainsFromTiles(_terrainsRoot.transform);

                        var terrainTileSize = Vector3.zero;
                        var maxCount        = _terrainsRoot.transform.childCount * ConfData.chunkData.SlicingCount *
                                              ConfData.chunkData.SlicingCount;
                        var progressCount = 0;
                        for (var i = 0; i < _terrainsRoot.transform.childCount; ++i)
                        {
                            var child = _terrainsRoot.transform.GetChild(i);
                            if (null == child)
                            {
                                continue;
                            }
                            if (false == child.gameObject.activeInHierarchy)
                            {
                                continue;
                            }

                            // 地形Tile尺寸
                            if (Vector3.zero.Equals(terrainTileSize))
                            {
                                terrainTileSize = TerrainsSettings.GetTerrainSize(child.gameObject);
                            }

                            // Tile Index
                            var tileIndex = GetTerrainTileIndexByPos(
                                baseOriginPos, child.transform.position,
                                terrainTileSize);

                            // 拆分地形
                            TerrainsSplit.Instance.SplitTerrains(
                                Settings.ChunkDataDir, child.gameObject, tileIndex,
                                maxLayerLevel, maxLayerLevel - _exportLayerLevel,
                                delegate(string iStatusTxt, bool iStatusCount)
                            {
                                if (iStatusCount)
                                {
                                    ++progressCount;
                                }
                                // 计算进度
                                var progress = progressCount / maxCount;
                                ProgressBarUpdate(iStatusTxt, progress);
                                this.Info("SplitTerrains:({0}) {1}", progress, iStatusTxt);
                            });
                        }

                        // 初始化地形拆分用的预制体信息
                        TerrainsSplit.Instance.InitPrefabsInfo(
                            ConfData.chunkData.StaticOnly, ConfData.chunkData.PrefabsExportDepthLimit);

                        ProgressBarUpdate(
                            "地形拆分成功", 1.0f);
                        // 到处此次地形拆分配置信息
                        TerrainsSettings.GetInstance().ExportBySceneName(CurSceneName);
                        ProgressBarClear();
                        // 刷新
                        AssetDatabase.Refresh();
                    }, Color.yellow);
                }
            }
        }