private static void callNative(NavMeshConfig config, SceneRecastData data, int currentMapID) { BytesWriteStream stream = new BytesWriteStream(); stream.setUseBitBoolean(false); config.write(stream); string cStr = ShineToolGlobal.mapInfoPath + "/navConfig.bin"; string dStr = SceneEditorWindow.getMapFilePathFront(currentMapID) + "_navData.bin"; string objStr = SceneEditorWindow.getMapFilePathFront(currentMapID) + "_navData.obj"; FileUtils.writeFileForBytesWriteStream(cStr, stream); stream.clear(); data.write(stream); FileUtils.writeFileForBytesWriteStream(dStr, stream); if (_needObjFile) { StringBuilder sb = new StringBuilder(); foreach (Vector3 vec in data.vertices) { sb.Append('v'); sb.Append(' '); sb.Append(vec.x); sb.Append(' '); sb.Append(vec.y); sb.Append(' '); sb.Append(vec.z); sb.Append('\n'); } int[] navIndices = data.triangles.getValues(); int len = data.triangles.size() / 3; for (int i = 0; i < len; i++) { sb.Append('f'); sb.Append(' '); sb.Append(navIndices[i * 3] + 1); sb.Append(' '); sb.Append(navIndices[i * 3 + 1] + 1); sb.Append(' '); sb.Append(navIndices[i * 3 + 2] + 1); sb.Append('\n'); } FileUtils.writeFileForUTF(objStr, sb.ToString()); } Ctrl.print("callJar"); ToolFileUtils.executeServerTool("exportNav", currentMapID.ToString()); Ctrl.print("OK"); }
/** 将当前场景的mesh写出到路径 */ public static void writeMesh(int currentMapID) { _needObjFile = CommonSetting.serverMapRecastNeedObjFile; MeshFilter[] mfs = Object.FindObjectsOfType <MeshFilter>(); Terrain[] terrains = Object.FindObjectsOfType <Terrain>(); if (terrains.Length > 1) { Ctrl.errorLog("地形数目非法"); return; } NavMeshConfig config = new NavMeshConfig(); SceneRecastData data = new SceneRecastData(); Terrain terrain = terrains.Length > 0 ? terrains[0] : null; Bounds b = new Bounds(); _newBound = true; if (terrain != null) { TerrainData terrainData = terrain.terrainData; Bounds terrainBounds = terrainData.bounds; terrainBounds.center = terrain.transform.TransformPoint(terrainBounds.center); // Bounds tBounds=new Bounds(new Vector3(terrainBounds.center.x, 0.0f, terrainBounds.center.z), new Vector3(ChunkSize, 1048576.0f, ChunkSize)); // // int sx = (int)Mathf.Floor(tBounds.center.x / ChunkSize); // int sz = (int) Mathf.Floor(tBounds.center.z / ChunkSize); // // var tilesPerChunks = (int)(ChunkSize / (config.tileSize * config.cellSize)); // // data.sizeX = tilesPerChunks; // data.sizeZ = tilesPerChunks; // data.originX = sx * tilesPerChunks; // data.originZ = sz * tilesPerChunks; // data.tileSize = config.tileSize * config.cellSize; if (_newBound) { _newBound = false; b = terrainBounds; } else { b.Encapsulate(terrainBounds); } SceneRecastTerrainData tData = data.terrain = new SceneRecastTerrainData(); tData.origin = terrainBounds.min; int rx = tData.resolutionX = terrainData.heightmapResolution; int rz = tData.resolutionZ = terrainData.heightmapResolution; Vector3 mapScale = terrainData.heightmapScale; tData.unit = mapScale; tData.unit.y /= 32768.0f; int startSize = data.triangles.size(); //terrain short[] heightSamples = tData.heightSamples = new short[tData.resolutionX * tData.resolutionZ]; float[,] rawHeights = terrainData.GetHeights(0, 0, terrainData.heightmapResolution, terrainData.heightmapResolution); int zm = rz - 1; int xm = rx - 1; for (int j = 0; j < rz; j++) { for (int i = 0; i < rx; i++) { float rawHeight = rawHeights[j, i]; if (_needObjFile) { data.vertices.add(new Vector3(i * mapScale.x, rawHeight * mapScale.y, j * mapScale.z)); } short sample = (short)(rawHeight * 32768.0f); if (sample < 0) { sample = 32767; } heightSamples[i + (j * rx)] = sample; if (_needObjFile) { if (j < zm && i < xm) { data.triangles.add(i + (j * rx)); data.triangles.add(i + ((j + 1) * rx)); data.triangles.add((i + 1) + ((j + 1) * rx)); data.triangles.add((i + 1) + ((j + 1) * rx)); data.triangles.add((i + 1) + (j * rx)); data.triangles.add(i + (j * rx)); } } } } if (_needObjFile) { if ((data.triangles.size() - startSize) != zm * xm * 6) { Ctrl.print("不对1"); } } //trees foreach (TreeInstance tree in terrainData.treeInstances) { GameObject treeObj = (GameObject)PrefabUtility.InstantiatePrefab(terrainData.treePrototypes[tree.prototypeIndex].prefab); treeObj.transform.position = Vector3.Scale(tree.position, terrainData.size) + terrain.transform.position; treeObj.transform.localScale = new Vector3(tree.widthScale, tree.heightScale, tree.widthScale); treeObj.transform.rotation = Quaternion.AngleAxis(tree.rotation * Mathf.Rad2Deg, Vector3.up); MeshFilter[] treeMeshFilters = treeObj.GetComponentsInChildren <MeshFilter>(); foreach (MeshFilter meshFilter in treeMeshFilters) { doOneMesh(data, meshFilter, ref b); } } } //meshes foreach (MeshFilter meshFilter in mfs) { doOneMesh(data, meshFilter, ref b); } int gx = (int)(b.size.x / config.cellSize + 0.5f); int gz = (int)(b.size.z / config.cellSize + 0.5f); int tz = (int)config.tileSize; data.sizeX = (gx + tz - 1) / tz; data.sizeZ = (gz + tz - 1) / tz; // data.sizeX = (int)(b.size.x / (config.tileSize * config.cellSize)); // data.sizeZ = (int)(b.size.z / (config.tileSize * config.cellSize)); int sx = (int)Mathf.Floor(b.min.x / data.sizeX); int sz = (int)Mathf.Floor(b.min.z / data.sizeZ); data.originX = sx * data.sizeX; data.originZ = sz * data.sizeZ; data.tileSize = config.tileSize * config.cellSize; data.min = b.min; data.min.y -= 1; data.max = b.max; data.max.y += 1; callNative(config, data, currentMapID); }