stl文件unity_Unity导入STL格式模型(二)
接上篇Unity导入STL格式模型(一),分成多个子网格的方式解决了导入慢以及目标模型顶点过多的问题,优化之后,目前针对二进制STL文件有比较良好的解析能力。
MeshCompression:是否使用压缩模式
Off为不使用,跳过压缩算法,导入模型的时间可以短到忽略不计。
On为使用,会为每个子网格单独压缩,也就是删掉所有他认为重复的顶点(位置相等他就认为重复)。
SingleTrianglesNumber:以此数量做为子网格的面数进行拆分,将模型分为多个子网格。
SaveMesh:是否保存模型的所有子网格至本地磁盘?在CreateInstance至Scene中之后。
核心代码如下:
///
/// 创建STL模型实例
///
private void CreateInstance()
{
if (_singleTrianglesNumber < 1000 || _singleTrianglesNumber > 20000)
{
Debug.LogError("Single Triangles Number: this value is unreasonable!");
return;
}
if (int.Parse(_trianglescount) > 200000)
{
Debug.LogError("Triangles Count: this value is too much!");
return;
}
string fullPath = Path.GetFullPath(AssetDatabase.GetAssetPath(target));
_total = int.Parse(_trianglescount);
_number = 0;
_binaryReader = new BinaryReader(File.Open(fullPath, FileMode.Open));
//抛弃前84个字节
_binaryReader.ReadBytes(84);
_vertices = new List();
_normals = new List();
_triangles = new List();
//读取顶点信息
Thread t = new Thread(ReadVertex);
t.Start();
while (_number < _total)
{
EditorUtility.DisplayProgressBar("读取信息", "正在读取顶点信息(" + _number + "/" + _total + ")......", (float)_number / _total);
}
CreateGameObject();
_binaryReader.Close();
EditorUtility.ClearProgressBar();
}
///
/// 读取顶点信息
///
private void ReadVertex()
{
while (_number < _total)
{
byte[] bytes;
bytes = _binaryReader.ReadBytes(50);
if (bytes.Length < 50)
{
_number += 1;
continue;
}
Vector3 vec0 = new Vector3(BitConverter.ToSingle(bytes, 0), BitConverter.ToSingle(bytes, 4), BitConverter.ToSingle(bytes, 8));
Vector3 vec1 = new Vector3(BitConverter.ToSingle(bytes, 12), BitConverter.ToSingle(bytes, 16), BitConverter.ToSingle(bytes, 20));
Vector3 vec2 = new Vector3(BitConverter.ToSingle(bytes, 24), BitConverter.ToSingle(bytes, 28), BitConverter.ToSingle(bytes, 32));
Vector3 vec3 = new Vector3(BitConverter.ToSingle(bytes, 36), BitConverter.ToSingle(bytes, 40), BitConverter.ToSingle(bytes, 44));
_normals.AddNormal(vec0);
_triangles.AddTriangle(_vertices.AddGetIndex(vec1), _vertices.AddGetIndex(vec2), _vertices.AddGetIndex(vec3));
_number += 1;
}
}
///
/// 创建GameObject
///
private void CreateGameObject()
{
string path = AssetDatabase.GetAssetPath(target);
string fullPath = Path.GetFullPath(path);
string assetPath = path.Substring(0, path.LastIndexOf("/")) + "/";
GameObject root = new GameObject(Path.GetFileNameWithoutExtension(fullPath));
root.transform.localPosition = Vector3.zero;
root.transform.localScale = Vector3.one;
int count = _total / _singleTrianglesNumber;
count += (_total % _singleTrianglesNumber > 0) ? 1 : 0;
for (int i = 0; i < count; i++)
{
GameObject tem = new GameObject(Path.GetFileNameWithoutExtension(fullPath) + "Sub" + i);
tem.transform.SetParent(root.transform);
tem.transform.localPosition = Vector3.zero;
tem.transform.localScale = Vector3.one;
MeshFilter mf = tem.AddComponent();
MeshRenderer mr = tem.AddComponent();
int startIndex = i * _singleTrianglesNumber * 3;
int length = _singleTrianglesNumber * 3;
if ((startIndex + length) > _vertices.Count)
{
length = _vertices.Count - startIndex;
}
List vertices = _vertices.GetRange(startIndex, length);
List normals = _normals.GetRange(startIndex, length);
List triangles = _triangles.GetRange(0, length);
//压缩网格
if (_meshCompression.IsOn())
{
MeshCompression(tem.name, vertices, normals, triangles);
}
Mesh m = new Mesh();
m.name = tem.name;
m.vertices = vertices.ToArray();
m.normals = normals.ToArray();
m.triangles = triangles.ToArray();
m.RecalculateNormals();
mf.mesh = m;
mr.material = new Material(Shader.Find("Standard"));
Debug.Log("Create done! " + tem.name + ": Vertex Number " + m.vertices.Length);
}
}
///
/// 压缩网格
///
/// 网格名称
/// 需要压缩的网格顶点数组
/// 与之对应的法线数组
/// 与之对应的三角面数组
private void MeshCompression(string meshName, List vertices, List normals, List triangles)
{
//移位补偿,当顶点被标记为待删除顶点时
int offset = 0;
//需要删除的顶点索引集合
List removes = new List();
for (int i = 0; i < vertices.Count; i++)
{
EditorUtility.DisplayProgressBar("压缩网格", "正在压缩网格[ " + meshName + " ](" + i + "/" + vertices.Count + ")......", (float)i / vertices.Count);
if (removes.Contains(i))
{
offset += 1;
continue;
}
triangles[i] = i - offset;
for (int j = i + 1; j < vertices.Count; j++)
{
if (vertices[i] == vertices[j])
{
removes.Add(j);
triangles[j] = triangles[i];
}
}
}
removes.Sort();
removes.Reverse();
for (int i = 0; i < removes.Count; i++)
{
vertices.RemoveAt(removes[i]);
normals.RemoveAt(removes[i]);
}
}
测试:使用不压缩网格模式,点击CreateInstance,导入的时间快到可以忽略不计,而且目标已被拆分为多个网格,再多顶点的模型也不用担心超过上限:
没有经过压缩的顶点数量分别为:
测试:然后我们使用压缩网格模式,点击CreateInstance,注意,这里勾选SaveMesh,以便于将网格保存在本地,便可重复使用,毕竟压缩模式导入比较慢,不用每次使用都重新压缩网格:
压缩之后的结果:
可以看到顶点几乎被压缩掉了四分之三,如果要考虑性能的话,还是使用压缩网格比较好,而且因为他替换掉的都是位置重复顶点,这些在视觉上是看不出任何差异的(没有贴图的话),而且我们保存在本地的Mesh文件之后便可以直接通过拖拽给MeshFilter组件使用,方便了很多。
github源码链接:https://github.com/SaiTingHu/ImportSTL
来自:http://blog.csdn.net/qq992817263/article/details/72738344
stl文件unity_Unity导入STL格式模型(二)相关推荐
- stl文件unity_Unity导入STL格式模型(一)
STL文件是一种非常简单且实用的三角形网格文件,他只按照三角面片的方式存储了所有的面信息及法矢量,不包含纹理以及其他任何媒体信息,主要存储格式分为:ASCII码格式.二进制格式. 这种文件格式在工业上 ...
- python 读取stl文件_读取STL模型 并用opengl显示
说起STL模型,相信使用过CAD三维软件的人都不陌生, STL = STL文件,一种3D模型文件格式STL(STereo Lithography的缩写) STL文件格式是由3D SYSTEMS 公司于 ...
- unity如何支持stl文件的导入
stl文件为扫描生成的3d物体文件.stl原生是不支持stl导入的. 支持的方法也很简单: 打开Packages/manifest.json 将"co.parabox.stl":& ...
- Three导入dae格式模型实例
DAE 是纯文本的模型格式,其本质就是一个单纯的xml文件.相比fbx,对dae格式模型的载入我们拥有非常高的自由控制,这也是最复杂的地方.基本上,dae文件内一开始就把数据分成了好几大块.对我们来说 ...
- ANSYS APDL学习(3):ANSYS APDL 导入x_t格式模型并受力分析范例
ANSYS APDL 导入x_t格式模型并受力分析范例 第一步:导入模型 第二步:设置单元类型 第三步:划分网格 第四步:材料属性 第五步:施加位移约束和力 第七步:计算 第八步:查看结果 附上 命令 ...
- 旋转狗头:Python如何读取STL文件,生成STL文件预览图(缩略图)之进化,动态旋转Gif图
之前的文章<Python如何读取STL文件,生成STL文件预览图(缩略图)>实现了将STL文件读取加载.绘制保存为某个角度下2D的png图片,作为预览图(缩略图).但是3D转2D,预览就丢 ...
- matlab读入stl文件,matlab读取stl文件
设定 Facet Surface Smoothing (三角面片平滑)为 150 -> File (文件) -> Export (输出) -> 选择 .STL Mechanical ...
- Python如何读取STL文件,生成STL文件预览图(缩略图)
如果你的项目也遇到了需要在后台将STL文件自动处理并生成预览图(缩略图)的需求,那么看本文就可以实现.如下图,我有一个狗头. 后台处理后生成的效果1: 后台处理后生成的效果2: 后台处理后生成的效果3 ...
- PostGIS FME导入fbx格式模型
使用FME导入模型数据到PostGIS FME支持模型格式:fbx.obj.dae.stl.3ds(目前仅打通fbx) 环境: Win10 FME2020 Fbx格式数据 操作说明: 1.打开FME ...
- stl文件转stp (二次开发)
前几天有个美女问我stl文件怎么处理,很尴尬我也处理不了,为了避免再次发生这种情况,所以我做了这个小软件.其下载链接将在文末给出.源码我已经上传GitHub,需要的可自取:https://github ...
最新文章
- tcp转串口_PROFIBUS DP与Modbus/TCP网络转换操作指南
- php.ini网站空白,php配置问题:拷贝php.ini后,测试页面无法显示(显示空白)
- Java面试基础篇——第九篇:BIO,NIO,AIO的区别
- 快速打开计算机磁盘的软件,提升电脑运行效率, 你需要快速整理磁盘碎片的工具...
- Grpc Proto To Nuget Package 插件使用说明
- C#LeetCode刷题之#530-二叉搜索树的最小绝对差(Minimum Absolute Difference in BST)
- Python可视化:Seaborn(三)
- java计算器算法描述_基于Java的计算器算法(源代码)
- 职教云怎么合并账号_云课堂智慧职教怎么注销账号
- “零基础圆梦华为RS HCNP”视频课程规划
- Java 大地坐标转经纬度,经纬度与WGS84坐标转换
- JavaScript 索引、关联、对象数组增删改查循环
- 技术经理、架构师、技术总监、VP、CTO,这些岗位都是如何挣出来
- 修改db_create_file_dest
- 本地设置测试域名转向
- F. Fitness Baker
- 构建WindowsPhone生态:梁念坚博士答记者问windowsphone
- 使用python爬取百度今日热点事件排行榜
- Vue项目设置ico
- windows 自带计算器介绍
热门文章
- 你们要的网络电话软件测评来了
- windows功能_支持 AirPlay/DLNA 功能的 Windows 影音播放软件 5KPlayer
- 复制文字到剪贴板的几种方法
- 2015061906 - firebug安装和下载(2)
- 重装系统后电脑只剩下C盘怎么办?怎样给电脑磁盘分区增加盘符?
- 计算机英语辅助翻译软件,计算机辅助翻译(CAT)软件 计算机辅助翻译(CAT)软件 v6.3.0.616...
- 你在家看电视,家里的电视也在看你?
- linux解压win10iso,ISO文件的解压和WINISO問題
- 【STM32训练—SIM900A模块】第二篇、STM32驱动SIM900A发送中文和英文短信
- GDI函数 StretchDIBits,StretchBlt 缩小图片会有黑点的问题解决办法