public void EditorTessEnd()
    {
        if (mTessellationJob == null || LOD == null)
        {
            return;
        }
        //save data
        MTQuadTreeHeader header = new MTQuadTreeHeader(DataName);

        header.QuadTreeDepth = QuadTreeDepth;
        header.BoundMin      = VolumnBound.min;
        header.BoundMax      = VolumnBound.max;
        header.LOD           = LOD.Length;
        foreach (var m in mTessellationJob.mesh)
        {
            MTMeshHeader mh = new MTMeshHeader(m.meshId, m.center);
            header.Meshes.Add(m.meshId, mh);
            MTFileUtils.SaveMesh(DataName, m);
        }
        MTLog.Log("mesh saved!");
        MTFileUtils.SaveQuadTreeHeader(DataName, header, Terrain.activeTerrain.terrainData.alphamapTextureCount);
        MTLog.Log("header saved!");
        string matPath = "Assets/MightyTerrainMesh/Resources";

        MTMatUtils.SaveMaterials(matPath, DataName, Terrain.activeTerrain);
        MTLog.Log("material saved!");
    }
    public void EditorCreateDataBegin()
    {
        if (DataName == "")
        {
            MTLog.LogError("data should have a name");
            return;
        }
        if (LOD == null || LOD.Length == 0)
        {
            MTLog.LogError("no lod setting");
            return;
        }
        if (Terrain.activeTerrain == null)
        {
            MTLog.LogError("no active terrain");
            return;
        }
        int gridMax = 1 << QuadTreeDepth;

        mCreateDataJob = new CreateDataJob(VolumnBound, gridMax, gridMax, LOD);
    }
 public void EditorCreatePreview()
 {
     if (DataName == "")
     {
         MTLog.LogError("data should have a name");
         return;
     }
     try
     {
         Transform[] lodParent = new Transform[LOD.Length];
         for (int i = 0; i < LOD.Length; ++i)
         {
             GameObject lodGo = new GameObject("lod" + i);
             lodGo.transform.parent = transform;
             lodParent[i]           = lodGo.transform;
         }
         MTQuadTreeHeader header = MTFileUtils.LoadQuadTreeHeader(DataName);
         foreach (var m in header.Meshes.Values)
         {
             Mesh[] lods = new Mesh[LOD.Length];
             MTFileUtils.LoadMesh(lods, DataName, m.MeshID);
             for (int i = 0; i < LOD.Length; ++i)
             {
                 MeshFilter   meshF;
                 MeshRenderer meshR;
                 GameObject   meshGo = new GameObject("meshObj");
                 meshGo.transform.parent = lodParent[i];
                 meshF            = meshGo.AddComponent <MeshFilter>();
                 meshR            = meshGo.AddComponent <MeshRenderer>();
                 meshR.materials  = header.RuntimeMats;
                 meshF.sharedMesh = lods[i];
             }
         }
     }
     catch
     {
         MTLog.LogError("failed to load datas");
     }
 }
示例#4
0
 private void Awake()
 {
     if (DataName == "")
     {
         return;
     }
     try
     {
         mHeader = MTFileUtils.LoadQuadTreeHeader(DataName);
         mRoot   = new MTQuadTreeNode(mHeader.QuadTreeDepth, mHeader.BoundMin, mHeader.BoundMax);
         foreach (var mh in mHeader.Meshes.Values)
         {
             mRoot.AddMesh(mh);
         }
         int gridMax = 1 << mHeader.QuadTreeDepth;
         mVisiblePatches = new MTArray <uint>(gridMax * gridMax);
         if (lodPolicy.Length < mHeader.LOD)
         {
             float[] policy = new float[mHeader.LOD];
             for (int i = 0; i < lodPolicy.Length; ++i)
             {
                 policy[i] = lodPolicy[i];
             }
             lodPolicy = policy;
         }
         lodPolicy[0] = Mathf.Clamp(lodPolicy[0], 0.5f * mRoot.Bound.size.x / gridMax, lodPolicy[0]);
         lodPolicy[lodPolicy.Length - 1] = float.MaxValue;
     }
     catch
     {
         mHeader = null;
         mRoot   = null;
         MTLog.LogError("MTLoader load quadtree header failed");
     }
     mCamera = GetComponent <Camera>();
 }
    //
    private void OnGUI()
    {
        Terrain curentTarget = EditorGUILayout.ObjectField("Convert Target", terrainTarget, typeof(Terrain), true) as Terrain;

        if (curentTarget != terrainTarget)
        {
            ClearAll();
            terrainTarget = curentTarget;
        }
        int curSliceCount = Mathf.FloorToInt(Mathf.Pow(2, QuadTreeDepth));
        int sliceCount    = EditorGUILayout.IntField("Slice Count(NxN)", curSliceCount);

        if (sliceCount != curSliceCount)
        {
            curSliceCount = Mathf.NextPowerOfTwo(sliceCount);
            QuadTreeDepth = Mathf.FloorToInt(Mathf.Log(curSliceCount, 2));
        }

        int lodCount = EditorGUILayout.IntField("LOD Count", LODSettings.Length);

        if (lodCount != LODSettings.Length)
        {
            MTLODSetting[] old = LODSettings;
            LODSettings = new MTLODSetting[lodCount];
            for (int i = 0; i < Mathf.Min(lodCount, old.Length); ++i)
            {
                LODSettings[i] = old[i];
            }
            for (int i = Mathf.Min(lodCount, old.Length); i < Mathf.Max(lodCount, old.Length); ++i)
            {
                LODSettings[i] = new MTLODSetting();
            }
        }
        if (LODSettings.Length > 0)
        {
            for (int i = 0; i < LODSettings.Length; ++i)
            {
                LODSettings[i].OnGUIDraw(i);
            }
        }
        BakeMaterial = EditorGUILayout.ToggleLeft("Bake Material", BakeMaterial);
        if (BakeMaterial)
        {
            BakeTexRes = EditorGUILayout.IntField("Bake Texture Resolution", BakeTexRes);
            BakeTexRes = Mathf.Min(2048, Mathf.NextPowerOfTwo(BakeTexRes));
        }
        if (GUILayout.Button("Generate"))
        {
            if (LODSettings == null || LODSettings.Length == 0)
            {
                MTLog.LogError("no lod setting");
                return;
            }
            if (terrainTarget == null)
            {
                MTLog.LogError("no target terrain");
                return;
            }
            string[] lodFolder = new string[LODSettings.Length];
            for (int i = 0; i < LODSettings.Length; ++i)
            {
                string guid = AssetDatabase.CreateFolder("Assets", string.Format("{0}_LOD{1}", terrainTarget.name, i));
                lodFolder[i] = AssetDatabase.GUIDToAssetPath(guid);
            }
            int gridMax = 1 << QuadTreeDepth;
            dataCreateJob = new CreateDataJob(terrainTarget.terrainData.bounds, gridMax, gridMax, LODSettings);
            for (int i = 0; i < int.MaxValue; ++i)
            {
                dataCreateJob.Update();
                EditorUtility.DisplayProgressBar("creating data", "scaning volumn", dataCreateJob.progress);
                if (dataCreateJob.IsDone)
                {
                    break;
                }
            }
            dataCreateJob.EndProcess();
            tessellationJob = new TessellationJob(dataCreateJob.LODs);
            for (int i = 0; i < int.MaxValue; ++i)
            {
                tessellationJob.Update();
                EditorUtility.DisplayProgressBar("creating data", "tessellation", tessellationJob.progress);
                if (tessellationJob.IsDone)
                {
                    break;
                }
            }
            for (int i = 0; i < tessellationJob.mesh.Length; ++i)
            {
                EditorUtility.DisplayProgressBar("saving data", "processing", (float)i / tessellationJob.mesh.Length);
                MTMeshData data = tessellationJob.mesh[i];
                for (int lod = 0; lod < data.lods.Length; ++lod)
                {
                    SaveMesh(lodFolder[lod], data.meshId, data.lods[lod], sliceCount);
                    if (!BakeMaterial)
                    {
                        MTMatUtils.SaveMaterials(lodFolder[lod], terrainTarget.name, terrainTarget);
                    }
                }
            }
            if (BakeMaterial)
            {
                string guid = AssetDatabase.CreateFolder("Assets", string.Format("{0}_BakedMats", terrainTarget.name));
                AssetDatabase.Refresh();
                RunBakeMaterial(AssetDatabase.GUIDToAssetPath(guid), terrainTarget, BakeTexRes);
            }
            EditorUtility.ClearProgressBar();
            AssetDatabase.Refresh();
        }
    }
    private void EditorGrabDetails(string folderName, Terrain terrainTarget, int layer)
    {
        if (terrainTarget == null)
        {
            MTLog.LogError("no active terrain");
            return;
        }
        TerrainData data           = terrainTarget.terrainData;
        int         detailLayerCnt = data.detailPrototypes.Length;
        int         dataLen        = data.detailResolution * data.detailResolution;

        string[] savedAssets = new string[detailLayerCnt];
        Bounds   bound       = data.bounds;
        float    pixelSize   = bound.size.x / data.detailResolution;

        for (int i = 0; i < detailLayerCnt; ++i)
        {
            MemoryStream ms       = new MemoryStream();
            int          totalCnt = 0;
            MTFileUtils.WriteInt(ms, totalCnt);
            DetailPrototype proto = data.detailPrototypes[i];
            //prototype info
            //raw data
            int[,] dlayer = data.GetDetailLayer(0, 0, data.detailResolution, data.detailResolution, i);
            for (int u = 0; u < data.detailResolution; ++u)
            {
                for (int v = 0; v < data.detailResolution; ++v)
                {
                    ushort pixelDen = (ushort)dlayer[v, u];
                    //gen data inside
                    if (pixelDen <= 0)
                    {
                        continue;
                    }
                    //data count
                    long countOffset = ms.Position;
                    MTFileUtils.WriteUShort(ms, pixelDen);
                    int    subGridSize  = Mathf.CeilToInt(Mathf.Sqrt(pixelDen));
                    float  start_x      = bound.min.x + u * pixelSize;
                    float  start_z      = bound.min.z + v * pixelSize;
                    ushort spawnedCount = SpawnOnePixel(proto, layer, start_x, start_z, pixelSize, subGridSize, pixelDen, bound.max.y, ms);
                    if (countOffset != pixelDen)
                    {
                        long posCache = ms.Position;
                        ms.Position = countOffset;
                        MTFileUtils.WriteUShort(ms, spawnedCount);
                        ms.Position = posCache;
                    }
                    totalCnt += spawnedCount;
                    EditorUtility.DisplayProgressBar("bake details", "processing", (float)(u * data.detailResolution + v) / (data.detailResolution * data.detailResolution));
                }
            }
            ms.Position = 0;
            MTFileUtils.WriteInt(ms, totalCnt);
            savedAssets[i] = ExportDensity2Bytes(folderName, i, ms);
            ms.Close();
        }
        EditorUtility.ClearProgressBar();
        AssetDatabase.Refresh();

        //add componet and parameter
        GameObject prefabObj = new GameObject("detail_layers");

        prefabObj.transform.position = terrainTarget.transform.position;
        MTDetailBatchRenderer dr = prefabObj.AddComponent <MTDetailBatchRenderer>();

        dr.layers = new MTDetailBatchRenderer.ProtoLayerInfo[detailLayerCnt];
        for (int i = 0; i < detailLayerCnt; ++i)
        {
            DetailPrototype proto = data.detailPrototypes[i];
            if (savedAssets[i] == null || proto.prototype == null)
            {
                continue;
            }
            MeshFilter mf = proto.prototype.GetComponent <MeshFilter>();
            if (mf == null)
            {
                continue;
            }
            MeshRenderer mr = proto.prototype.GetComponent <MeshRenderer>();
            if (mr == null)
            {
                continue;
            }
            TextAsset asset = AssetDatabase.LoadAssetAtPath <TextAsset>(savedAssets[i]);
            dr.layers[i]            = new MTDetailBatchRenderer.ProtoLayerInfo();
            dr.layers[i].detailData = asset;
            dr.layers[i].mesh       = mf.sharedMesh;
            dr.layers[i].mat        = mr.sharedMaterial;
        }
        dr.bnds = bound;
        //dr.detailShader = AssetDatabase.LoadAssetAtPath<ComputeShader>("Assets/MightyTerrainMesh/Shaders/TerrainDetailMask");
        dr.detailDistance           = Terrain.activeTerrain.detailObjectDistance;
        dr.detailDensity            = Terrain.activeTerrain.detailObjectDensity;
        dr.detailResolution         = data.detailResolution;
        dr.detailResolutionPerPatch = data.detailResolutionPerPatch;

        string prefabPath = Path.Combine(folderName, "detail_layers.prefab");

        PrefabUtility.SaveAsPrefabAsset(prefabObj, prefabPath);
        DestroyImmediate(prefabObj);
        AssetDatabase.Refresh();
    }