{"id":2271,"date":"2020-09-03T22:34:02","date_gmt":"2020-09-03T14:34:02","guid":{"rendered":"http:\/\/blog.coolcoding.cn\/?p=2271"},"modified":"2020-09-04T13:35:35","modified_gmt":"2020-09-04T05:35:35","slug":"unityrenderdoc%e7%9a%84csv%e5%af%bc%e5%87%ba%e5%88%b0unity-mesh","status":"publish","type":"post","link":"https:\/\/blog.coolcoding.cn\/?p=2271","title":{"rendered":"[Unity]RenderDoc\u7684CSV\u5bfc\u51fa\u5230Unity-Mesh"},"content":{"rendered":"\n<pre class=\"wp-block-code\"><code>#if UNITY_EDITOR\n\nusing System.Collections;\nusing System.Collections.Generic;\nusing UnityEngine;\nusing UnityEditor;\n\npublic class EditorRenderDocMeshImport\n{\n    [MenuItem(\"Assets\/ImportMeshFromRenderDoc\")]\n    public static void Execute()\n    {\n        var ret = ImportMeshFromRenderDoc(\"Assets\/1.csv\", true, true);\n        if (ret != 0)\n        {\n            Log.Error(\"ImportFail, Ret={0}\", ret);\n        }\n    }\n\n    public static int ImportMeshFromRenderDoc(string importFilename, bool needRotationN90, bool reverseUvY)\n    {\n        if (!System.IO.File.Exists(importFilename))\n        {\n            return -1;\n        }\n\n        string clipboard = System.IO.File.ReadAllText(importFilename);\n        var allTexts = clipboard.Split('\\n');\n        if (allTexts.Length &lt;= 1)\n        {\n            return -2;\n        }\n\n        var heads = allTexts[0].Trim().Replace(\" \", \"\").Split(',');\n        List&lt;float[]> allRows = new List&lt;float[]>();\n        ReadAllRows(allTexts, heads.Length, ref allRows);\n\n        var IDX = GetColumnIndex(heads, \"IDX\");\n        var position_x = GetColumnIndex(heads, \"position.x\");\n        var position_y = GetColumnIndex(heads, \"position.y\");\n        var position_z = GetColumnIndex(heads, \"position.z\");\n        var uv_x = GetColumnIndex(heads, \"uv.x\");\n        var uv_y = GetColumnIndex(heads, \"uv.y\");\n        var normal_x = GetColumnIndex(heads, \"normal.x\");\n        var normal_y = GetColumnIndex(heads, \"normal.y\");\n        var normal_z = GetColumnIndex(heads, \"normal.z\");\n\n        if (IDX &lt; 0 || position_x &lt; 0 || position_y &lt; 0 || position_z &lt; 0\n            || uv_x &lt; 0 || uv_y &lt; 0)\n        {\n            Log.Error(\"ImportFail: pos={0},{1},{2}; uv={3},{4}\", position_x, position_y, position_z, uv_x, uv_y);\n            return -3;\n        }\n\n        bool hasNormalProp = (normal_x >= 0 &amp;&amp; normal_y >= 0 &amp;&amp; normal_z >= 0);\n        int minIndex = 65535;\n        int maxIndex = 0;\n        for (int i = 0; i &lt; allRows.Count; ++i)\n        {\n            int currIndex = (int)allRows[i][IDX];\n            if (currIndex &lt; minIndex)\n            {\n                minIndex = currIndex;\n            }\n            else if (currIndex > maxIndex)\n            {\n                maxIndex = currIndex;\n            }\n        }\n\n        int vertexLength = maxIndex - minIndex + 1; \/\/ Container Self Index.\n        int indexLen = allRows.Count;\n        if (indexLen % 3 != 0)\n        {\n            Log.Error(\"DataException, Number={0}\", indexLen);\n            return -4;\n        }\n\n        Vector3[] outputVertexs = new Vector3[vertexLength];\n        Vector3[] outputNormals = new Vector3[vertexLength];\n        Vector2[] outputUvs = new Vector2[vertexLength];\n        int[] outputIndexBuff = new int[indexLen];\n        var rotationN90 = needRotationN90 ? Quaternion.Euler(-90, 0, 0) : Quaternion.identity;\n        for (int i = 0; i &lt; allRows.Count; ++i)\n        {\n            var currLine = allRows[i];\n            var realIndex = (int)currLine[IDX] - minIndex;\n            outputIndexBuff[i] = realIndex;\n            if (realIndex &lt; outputVertexs.Length &amp;&amp; realIndex >= 0)\n            {\n                var p = new Vector3(currLine[position_x], currLine[position_y], currLine[position_z]);\n                outputVertexs[realIndex] = rotationN90 * p;\n                if (hasNormalProp)\n                {\n                    outputNormals[realIndex] = new Vector3(currLine[normal_x], currLine[normal_y], currLine[normal_z]);\n                }\n                outputUvs[realIndex] = new Vector2(currLine[uv_x], reverseUvY ? 1 - currLine[uv_y] : currLine[uv_y]);\n            }\n            else\n            {\n                Log.Error(\"DataException:{0}, {1}, {2}, {3}\", realIndex, outputVertexs.Length, minIndex, currLine[IDX]);\n                return -5;\n            }\n        }\n\n        Mesh mesh = new Mesh();\n        mesh.vertices = outputVertexs;\n        mesh.SetTriangles(outputIndexBuff, 0);\n        mesh.uv = outputUvs;\n        if (hasNormalProp)\n        {\n            mesh.normals = outputNormals;\n        }\n        else\n        {\n            mesh.RecalculateNormals();\n        }\n        CreateMeshAssetAndShow(mesh);\n        return 0;\n    }\n\n    private static void CreateMeshAssetAndShow(Mesh mesh)\n    {\n        var outputName = System.DateTime.Now.Ticks.ToString();\n        var outputMeshFilename = string.Format(\"Assets\/{0}.asset\", outputName);\n        AssetDatabase.CreateAsset(mesh, outputMeshFilename);\n\n        var shader = Shader.Find(\"Standard\");\n        var outputMatFilename = string.Format(\"Assets\/{0}.mat\", outputName);\n        Material mat = new Material(shader);\n        AssetDatabase.CreateAsset(mat, outputMatFilename);\n\n        var meshRes = AssetDatabase.LoadAssetAtPath(outputMeshFilename, typeof(Mesh)) as Mesh;\n        var matRes = AssetDatabase.LoadAssetAtPath(outputMatFilename, typeof(Material)) as Material;\n\n        if (meshRes != null)\n        {\n            GameObject newObj = new GameObject();\n            var mf = newObj.AddComponent&lt;MeshFilter>();\n            mf.sharedMesh = meshRes;\n\n            var mr = newObj.AddComponent&lt;MeshRenderer>();\n            mr.sharedMaterial = matRes;\n        }\n    }\n\n    private static void ReadAllRows(string[] allTexts, int headsLength, ref List&lt;float[]> allRows)\n    {\n        for (int lineIndex = 1; lineIndex &lt; allTexts.Length; ++lineIndex)\n        {\n            var lineText = allTexts[lineIndex];\n            if (lineText.Length &lt;= 10)\n            {\n                continue;\n            }\n\n            var cells = lineText.Trim().Replace(\" \", \"\").Split(',');\n            if (cells.Length != headsLength)\n            {\n                continue;\n            }\n\n            float[] cellData = new float[cells.Length];\n            for (int i = 0; i &lt; cells.Length; ++i)\n            {\n                float v = 0;\n                if (float.TryParse(cells[i], out v))\n                {\n                    cellData[i] = v;\n                }\n                else\n                {\n                    Log.Error(\"DataInvalid, {0},{1} = {2}\", lineIndex, i, cells[i]);\n                }\n            }\n\n            allRows.Add(cellData);\n        }\n    }\n\n    public static int GetColumnIndex(string[] input, string key)\n    {\n        for(int i=0; i&lt;input.Length; ++i)\n        {\n            if (input[i] == key)\n            {\n                return i;\n            }\n        }\n\n        return -1;\n    }\n}\n\n#endif<\/code><\/pre>\n","protected":false},"excerpt":{"rendered":"","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[6],"tags":[57,18],"_links":{"self":[{"href":"https:\/\/blog.coolcoding.cn\/index.php?rest_route=\/wp\/v2\/posts\/2271"}],"collection":[{"href":"https:\/\/blog.coolcoding.cn\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.coolcoding.cn\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.coolcoding.cn\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.coolcoding.cn\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=2271"}],"version-history":[{"count":3,"href":"https:\/\/blog.coolcoding.cn\/index.php?rest_route=\/wp\/v2\/posts\/2271\/revisions"}],"predecessor-version":[{"id":2274,"href":"https:\/\/blog.coolcoding.cn\/index.php?rest_route=\/wp\/v2\/posts\/2271\/revisions\/2274"}],"wp:attachment":[{"href":"https:\/\/blog.coolcoding.cn\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=2271"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.coolcoding.cn\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=2271"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.coolcoding.cn\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=2271"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}