Snippets

Volumes of Fun Export TerrainVolume as mesh prefab

Created by David Williams
using System.Collections;
using System.Collections.Generic;
using System.IO;
using UnityEngine;
using Cubiquity;

#if UNITY_EDITOR
using UnityEditor;
#endif

public class VoxelTerrainToMesh : MonoBehaviour {
#if UNITY_EDITOR
    public TerrainVolume terrainVolume;

    bool Exported = false;

    MeshFilter filter;
    new MeshRenderer renderer;
    new MeshCollider collider;
    Material[] meshMaterials;
    Mesh tempMesh;
    GameObject newObj;
    GameObject tempObj;
    protected GameObject RecursiveMeshExport(string MeshFolder, GameObject Obj, GameObject ParentObj) {
        newObj = null;
        if (Obj != null) {
            newObj = new GameObject(Obj.name);
            newObj.transform.position = Obj.transform.position;
            newObj.transform.rotation = Obj.transform.rotation;
            newObj.transform.localScale = Obj.transform.localScale;
            newObj.transform.SetParent(ParentObj.transform);
            
            filter = Obj.GetComponent<MeshFilter>();
            if (filter != null && filter.sharedMesh != null) {
                if (filter.sharedMesh.vertices.Length > 3) {
                    string MeshFile = MeshFolder + "/" + Obj.name + ".obj";

                    if (!Directory.Exists(MeshFolder)) {
                        Directory.CreateDirectory(MeshFolder);
                    }

                    tempMesh = Instantiate(filter.mesh);
                    AssetDatabase.CreateAsset(tempMesh, MeshFile);
                    AssetDatabase.SaveAssets();

                    filter = newObj.AddComponent<MeshFilter>();

                    filter.sharedMesh = tempMesh;//Resources.Load<Mesh>(MeshFile);
                    renderer = Obj.GetComponent<MeshRenderer>();

                    if (renderer != null) {
                        meshMaterials = renderer.sharedMaterials;

                        renderer = newObj.AddComponent<MeshRenderer>();
                        renderer.sharedMaterials = meshMaterials;

                        collider = newObj.AddComponent<MeshCollider>();
                        collider.sharedMesh = tempMesh;
                    }
                } else {
                    Debug.Log("Excluding Single Triangle Mesh");
                }
            }

            if (Obj.transform.childCount > 0) {
                for (int c = 0; c < Obj.transform.childCount; c++) {
                    tempObj = RecursiveMeshExport(MeshFolder, Obj.transform.GetChild(c).gameObject, newObj);
                    if (tempObj != null) {
                        tempObj.transform.SetParent(ParentObj.transform);
                    }
                }
            }
        }
        return newObj;
    }

    public void VolumeFinished() {
        Debug.Log("Volume Finished");
        if (terrainVolume != null) {
            string FilePath = "Assets/Drone/Terrains/" + name;

            //TODO: Recurse Octree, grab all Meshes, combine, then write to file
            Debug.Log("Attempting Mesh Export to \"" + FilePath + "\"");
            Cubiquity.Impl.OctreeNode OctNode = GetComponentInChildren<Cubiquity.Impl.OctreeNode>();
            if (OctNode != null) {
                Vector3 OriginalScale = transform.localScale;
                Vector3 OriginalPosition = transform.position;
                Quaternion OriginalRotation = transform.rotation;
                transform.localScale = Vector3.one;
                transform.position = Vector3.zero;
                transform.rotation = Quaternion.identity;

                GameObject NewPrefab = new GameObject(name + "_mesh");
                RecursiveMeshExport(FilePath, OctNode.gameObject, NewPrefab);
                NewPrefab.transform.localScale = OriginalScale;
                NewPrefab.transform.position = OriginalPosition;
                NewPrefab.transform.rotation = OriginalRotation;
                PrefabUtility.CreatePrefab(FilePath + "_mesh.prefab", NewPrefab);

                transform.localScale = OriginalScale;
                transform.position = OriginalPosition;
                transform.rotation = OriginalRotation;
            }
        }
        terrainVolume.OnMeshSyncComplete -= VolumeFinished;
        terrainVolume.OnMeshSyncLost -= VolumeFailed;

        Exported = true;
    }

    public void VolumeFailed() {
        Debug.Log("Volume Failed");
        terrainVolume.OnMeshSyncComplete -= VolumeFinished;
        terrainVolume.OnMeshSyncLost -= VolumeFailed;
    }

    private void Start() {
        if (!Exported) {
            terrainVolume = GetComponent<TerrainVolume>();
            if (terrainVolume != null) {
                terrainVolume.OnMeshSyncComplete += VolumeFinished;
                terrainVolume.OnMeshSyncLost += VolumeFailed;
            }
        } else {
            Destroy(this);
        }
    }
#endif
}

Comments (0)

HTTPS SSH

You can clone a snippet to your computer for local editing. Learn more.