[Unity]RenderDoc的CSV导出到Unity-Mesh

2020/09 03 22:09
#if UNITY_EDITOR

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;

public class EditorRenderDocMeshImport
{
    [MenuItem("Assets/ImportMeshFromRenderDoc")]
    public static void Execute()
    {
        var ret = ImportMeshFromRenderDoc("Assets/1.csv", true, true);
        if (ret != 0)
        {
            Log.Error("ImportFail, Ret={0}", ret);
        }
    }

    public static int ImportMeshFromRenderDoc(string importFilename, bool needRotationN90, bool reverseUvY)
    {
        if (!System.IO.File.Exists(importFilename))
        {
            return -1;
        }

        string clipboard = System.IO.File.ReadAllText(importFilename);
        var allTexts = clipboard.Split('\n');
        if (allTexts.Length <= 1)
        {
            return -2;
        }

        var heads = allTexts[0].Trim().Replace(" ", "").Split(',');
        List<float[]> allRows = new List<float[]>();
        ReadAllRows(allTexts, heads.Length, ref allRows);

        var IDX = GetColumnIndex(heads, "IDX");
        var position_x = GetColumnIndex(heads, "position.x");
        var position_y = GetColumnIndex(heads, "position.y");
        var position_z = GetColumnIndex(heads, "position.z");
        var uv_x = GetColumnIndex(heads, "uv.x");
        var uv_y = GetColumnIndex(heads, "uv.y");
        var normal_x = GetColumnIndex(heads, "normal.x");
        var normal_y = GetColumnIndex(heads, "normal.y");
        var normal_z = GetColumnIndex(heads, "normal.z");

        if (IDX < 0 || position_x < 0 || position_y < 0 || position_z < 0
            || uv_x < 0 || uv_y < 0)
        {
            Log.Error("ImportFail: pos={0},{1},{2}; uv={3},{4}", position_x, position_y, position_z, uv_x, uv_y);
            return -3;
        }

        bool hasNormalProp = (normal_x >= 0 && normal_y >= 0 && normal_z >= 0);
        int minIndex = 65535;
        int maxIndex = 0;
        for (int i = 0; i < allRows.Count; ++i)
        {
            int currIndex = (int)allRows[i][IDX];
            if (currIndex < minIndex)
            {
                minIndex = currIndex;
            }
            else if (currIndex > maxIndex)
            {
                maxIndex = currIndex;
            }
        }

        int vertexLength = maxIndex - minIndex + 1; // Container Self Index.
        int indexLen = allRows.Count;
        if (indexLen % 3 != 0)
        {
            Log.Error("DataException, Number={0}", indexLen);
            return -4;
        }

        Vector3[] outputVertexs = new Vector3[vertexLength];
        Vector3[] outputNormals = new Vector3[vertexLength];
        Vector2[] outputUvs = new Vector2[vertexLength];
        int[] outputIndexBuff = new int[indexLen];
        var rotationN90 = needRotationN90 ? Quaternion.Euler(-90, 0, 0) : Quaternion.identity;
        for (int i = 0; i < allRows.Count; ++i)
        {
            var currLine = allRows[i];
            var realIndex = (int)currLine[IDX] - minIndex;
            outputIndexBuff[i] = realIndex;
            if (realIndex < outputVertexs.Length && realIndex >= 0)
            {
                var p = new Vector3(currLine[position_x], currLine[position_y], currLine[position_z]);
                outputVertexs[realIndex] = rotationN90 * p;
                if (hasNormalProp)
                {
                    outputNormals[realIndex] = new Vector3(currLine[normal_x], currLine[normal_y], currLine[normal_z]);
                }
                outputUvs[realIndex] = new Vector2(currLine[uv_x], reverseUvY ? 1 - currLine[uv_y] : currLine[uv_y]);
            }
            else
            {
                Log.Error("DataException:{0}, {1}, {2}, {3}", realIndex, outputVertexs.Length, minIndex, currLine[IDX]);
                return -5;
            }
        }

        Mesh mesh = new Mesh();
        mesh.vertices = outputVertexs;
        mesh.SetTriangles(outputIndexBuff, 0);
        mesh.uv = outputUvs;
        if (hasNormalProp)
        {
            mesh.normals = outputNormals;
        }
        else
        {
            mesh.RecalculateNormals();
        }
        CreateMeshAssetAndShow(mesh);
        return 0;
    }

    private static void CreateMeshAssetAndShow(Mesh mesh)
    {
        var outputName = System.DateTime.Now.Ticks.ToString();
        var outputMeshFilename = string.Format("Assets/{0}.asset", outputName);
        AssetDatabase.CreateAsset(mesh, outputMeshFilename);

        var shader = Shader.Find("Standard");
        var outputMatFilename = string.Format("Assets/{0}.mat", outputName);
        Material mat = new Material(shader);
        AssetDatabase.CreateAsset(mat, outputMatFilename);

        var meshRes = AssetDatabase.LoadAssetAtPath(outputMeshFilename, typeof(Mesh)) as Mesh;
        var matRes = AssetDatabase.LoadAssetAtPath(outputMatFilename, typeof(Material)) as Material;

        if (meshRes != null)
        {
            GameObject newObj = new GameObject();
            var mf = newObj.AddComponent<MeshFilter>();
            mf.sharedMesh = meshRes;

            var mr = newObj.AddComponent<MeshRenderer>();
            mr.sharedMaterial = matRes;
        }
    }

    private static void ReadAllRows(string[] allTexts, int headsLength, ref List<float[]> allRows)
    {
        for (int lineIndex = 1; lineIndex < allTexts.Length; ++lineIndex)
        {
            var lineText = allTexts[lineIndex];
            if (lineText.Length <= 10)
            {
                continue;
            }

            var cells = lineText.Trim().Replace(" ", "").Split(',');
            if (cells.Length != headsLength)
            {
                continue;
            }

            float[] cellData = new float[cells.Length];
            for (int i = 0; i < cells.Length; ++i)
            {
                float v = 0;
                if (float.TryParse(cells[i], out v))
                {
                    cellData[i] = v;
                }
                else
                {
                    Log.Error("DataInvalid, {0},{1} = {2}", lineIndex, i, cells[i]);
                }
            }

            allRows.Add(cellData);
        }
    }

    public static int GetColumnIndex(string[] input, string key)
    {
        for(int i=0; i<input.Length; ++i)
        {
            if (input[i] == key)
            {
                return i;
            }
        }

        return -1;
    }
}

#endif

1 Comment