教你如何使用GPA导出模型,另送一个 GPA CSV2MESH Tool in unity

Posted Jave.Lin

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了教你如何使用GPA导出模型,另送一个 GPA CSV2MESH Tool in unity相关的知识,希望对你有一定的参考价值。

文章目录


以前写过一篇:Unity - RenderDoc 抓帧导出 FBX(带UV)


吐槽

我估计GPA是怕收律师函,因为如果 GPA 将所有资源一键提取,一键导出,那么可能很多开发商会告他


GPA Geometry Output 没有 UV

可以看到也好几个帖子问 GPA 官方,都是被官方忽悠回答了:

(除了这个,我自己还搜索过还几个类似有人问这个问题,结果同样被官方忽悠)



既然GPA不整模型导出带UV,那么今天我们实现一个 GPA 中的模型导出 UV 的工具


问题实例

如果直接将 input gemoetry 导出
会得到一个除了 position 之外,没有其他数据的网格,如下:

然后,对应的 shader vs input 有6个 register

如果我们要向将这些顶点数据都导出来,直接使用 GPA 功能默认的Geometry output是导不出来的


开始实现


提取 VBV, IBV

上面的 VS_INPUT 可以看到 input attribute 的定义

但是这些数据是从哪些 VBV(vertex buffer viewer) 输入的呢?

我们可以点击 Resource 中的 Shader,选择:Vertex shader 后

然后查看使用到的数据有哪些,如下图:

OK,留意:

然后我们可以将每个 VBV 个、单个 IBV 设置导出 CSV Titles 格式,下面以导出 position.csv 为例

  • 根据shader input attribute 定义,定位使用的 vbv序号
  • 在 resource 中,找到对应的 vbv
  • 给 vbv 的 titles 设置好格式
  • 最后 导出 csv


其他的 tangent, normal, uv0, uv1, color0 都可以使用类似的方式导出,如上图,这个模型的数据我是使用下面的格式导出的
因为我们使用的是 unity mesh,那么TEXCOORD0 的 position 我们需要将其 semantic 修改为 POSITION,同理,normal 和 uv0 都使用对应的:NORMAL, TEXCOORD0 来替代

参考如下(注意每个 shader 的 VBV 是干嘛用的,需要自行去查看 shader 怎么使用,以此分析他们的所属的 semantic,因为每个 shader 都有可能不一样):

VBV, IBV 导出的 csv format:

  • position : VBV1 - float POSITION.x;float POSITION.y;float POSITION.z;

  • tangent : VBV2 - float TANGENT.x;float TANGENT.y;float TANGENT.z;float TANGENT.w;

  • normal : VBV3 - float NORMAL.x;float NORMAL.y;float NORMAL.z;

  • uv0 : VBV0 - half TEXCOORD0.x;half TEXCOORD0.y;byte4p

  • uv1 : VBV0 - byte4p; half TEXCOORD4.x;half TEXCOORD4.y;

  • color0 : VBV1

    • float TEXCOORD5.x;float TEXCOORD5.y;float TEXCOORD5.z;float TEXCOORD5.w; byte4p
    • ubyte COLOR0.x;ubyte COLOR0.y;ubyte COLOR0.z;ubyte COLOR0.w; byte4p
    • ubyte TEXCOORD5.x;ubyte TEXCOORD5.y;ubyte TEXCOORD5.z;ubyte TEXCOORD5.w; byte4p - 这个会使用比较多,但是这个有些问题:没有 normalized
    • nubyte TEXCOORD5.x;nubyte TEXCOORD5.y;nubyte TEXCOORD5.z;nubyte TEXCOORD5.w; byte4p - 然后添加了前缀 n 后,还是不能 normalized,所以这个我在工具中特殊弄了一些开关,可是设置 VBV 是否需要 normalized
  • index : IBV - 不需要格式,直接导出,只要确保第二列是 index 的值即可


工具演示导出


GPA 的 VBV,IBV的 BUG

我之前就怀疑还原模型的话,如果这些 IBV, VBV 长度都不对的话,除了浪费数据,还可能出问题

因为很多 VBV 和 IBV 的元素数量是对不上的

今天在抓帧某个角色的 卧蚕(眼部底下部分) 模型时候就出现这个问题

从下面的 IBV 可以看到1091,1092 之间的索引跨度很大,是有问题的

23901 的索引直接就超出了 VBV 顶点总数的数量

从下面的数据分析, Primitive 总数才 364 个三角形

VBV position 数量才 10313,但是 IBV 的索引已经远超这个范围了,这个很明显是 GPA 的数据显示上的 BUG

所以部分模型的导出可能遇到:

  • Fail setting triangles. Some indices are referencing out of bounds vertices. IndexCount: 2046, VertexCount: 10314
  • Fail setting triangles. The number of supplied triangle indices must be a multiple of 3.



must be a multiple of 3 的解决办法

在我的工具中,是这么来处理的:

因为是在 set triangles 的时候发生的错误

那么我们只要将 indices 的长度保持在 缓存元素数量可以整除3即可:indices.Count % 3 == 0

        // jave.lin : push padding or remove padding
        // jave.lin : 这么处理可以避免 https://blog.csdn.net/linjf520/article/details/127066726 文章中提及的 BUG:
        //  - Fail setting triangles. Some indices are referencing out of bounds vertices. IndexCount: xxx, VertexCount: xxx
        //  - Fail setting triangles. The number of supplied triangle indices must be a multiple of 3.
        if (indices.Count > 0 && indices.Count % 3 != 0)
        
            var loopCount = 0;
            var lastOneVal = indices[indices.Count - 1];
            var lastOneIsZeroVal = lastOneVal == 0;
            while (indices.Count > 0 && indices.Count % 3 != 0)
            
                if (loopCount > 10)
                    break;
                loopCount++;
                if (lastOneIsZeroVal)
                
                    // jave.lin : remove padding 如果尾部是 0 索引,我们可以用删除 padding 的方式
                    indices.RemoveAt(indices.Count - 1);
                
                else
                
                    // jave.lin : push padding, 否则我们使用 push 最后一个顶点作为 padding 的方式
                    indices.Add(lastOneVal);
                
            
        

indices out of bounds vertices - 暂无解决方法

这个问题是 GPA 的 BUG
暂时无解,连 index 的数值都错了,我们是不可能知道正确的数值的,只能猜:比如,可能是 数据类型溢出?
就是新版本的 fbx 模型,可能使用了 index buffer 的索引值的压缩技术,可能在 GPA 中没有对应实现解析,那么肯定会有报错的

这个 index 索引值的压缩技术大概是这么个思路:

  • 如果 index < byte.MaxValue,那么 index 使用 byte 类型解析
  • 如果 index < ushort.MaxValue,那么 使用 ushort 类型解析
  • 如果 index < uint.MaxValue,那么 使用 uint 类型解析

Project

  • github 工程后续上传
  • 百度盘工程后续上传

References

如何根据GPA对数组列表进行升序排序? arraylist 包含一个对象数组。 (Java)[重复]

【中文标题】如何根据GPA对数组列表进行升序排序? arraylist 包含一个对象数组。 (Java)[重复]【英文标题】:How ro sort the array list in ascending order based on GPA? The arraylist is holding an array of objects. (Java) [duplicate] 【发布时间】:2019-08-20 23:17:01 【问题描述】:

我正在尝试根据 GPA 升序对这个数组列表进行排序。 Student 类封装了 3 条信息:学号、姓氏、平均绩点。

所以我需要使用gradePointAverage 对它们进行排序。

//student array
studentArray[0] = student;
studentArray[1] = new Student(9093891, "Brown", 2.55);
studentArray[2] = new Student(9301879, "Carson", 1.11);
studentArray[3] = new Student(3910880, "Deardon", 4.01);
studentArray[4] = new Student(8891783, "Ellis", 2.66);
studentArray[5] = new Student(3899132, "Fisher", 0.55);

//filling my studentlist
studentList.add(student);
studentList.add(studentArray[0]);
studentList.add(studentArray[1]);
studentList.add(studentArray[2]);
studentList.add(studentArray[3]);
studentList.add(studentArray[4]);

ArrayList<String> sortedArrayListDescending = studentList.sortDescending();

【问题讨论】:

我知道它说 studentList.sortDescending() 但即使这样也不起作用。那是在胡闹。我收到“错误:找不到符号” "我得到一个"错误:找不到符号"" 那是因为 List 中没有 sortDescendingsortAscending 方法,有 sort 方法它采用Comparator,它表示用于检查两个比较对象之间的机制是否相等,大于或小于第二个。 【参考方案1】:

使用Collections.sort()升序

Collections.sort(studentList,Comparator.comparingDouble(Student::getGradePointsAverage));

降序

Collections.sort(list,Comparator.comparingDouble(Student::getGradePointsAverage).reversed());

【讨论】:

以上是关于教你如何使用GPA导出模型,另送一个 GPA CSV2MESH Tool in unity的主要内容,如果未能解决你的问题,请参考以下文章

如何从 python 中的用户 2 值读取并找到最高 GPA?

使用一组学生及其各自的 GPA 对 GPA 进行各种计算

如何在php中按降序对数组进行排序?

如何根据成绩和学分计算 GPA?

ANSYS中我模型单位是mm,密度是8040kg/m3,弹性模量195GPa

如何根据GPA对数组列表进行升序排序? arraylist 包含一个对象数组。 (Java)[重复]