unity 导出 stl
Unity导出stl格式
stl是常用的3D打印格式,目前有不少文章介绍stl的,这里不多介绍。
导出stl分为ascii形式和二进制形式,区别在于ascii可以直接用文本文件打开查看,而二进制直接打开是乱码,但是二进制形式读写速度较快,生成的文件也比ascii要小很多。
开发环境
unity:2018.2.16 2019.3.15
模型查看工具:Meshlab2020.09 、 CAD Assistant
测试模型:assetstore 上 的 office building
核心模块
- ASCII形式 将单个mesh写出为stl
/// <summary>/// 将单个mesh数据使用StreamWrite写出为stl/// </summary>/// <param name="mesh">待导出的mesh</param>/// <param name="sw">输出流</param>/// <param name="trans">mesh对应的transform,用于将顶点法线转到世界空间</param>/// <param name="exchangeCoordinate">是否需要变换坐标手系,unity是左手坐标系,默认变换到右手坐标系</param>private static void ExportMeshToStl(Mesh mesh, StreamWriter sw, Transform trans, bool exchangeCoordinate = true){for (int j = 0; j < mesh.subMeshCount; j++){int[] tris;if (mesh.subMeshCount == 1){sw.Write("\nsolid " + mesh.name + "\n");tris = mesh.triangles;}else{sw.Write("\nsolid " + mesh.name + "_" + j + "\n");tris = mesh.GetIndices(j);}Vector3[] vertices = mesh.vertices;Vector3[] normals = mesh.normals;for (int i = 0; i < tris.Length / 3; i++){//法线变换到世界空间Vector3 nor1 = trans.TransformDirection(normals[tris[i * 3]]);Vector3 nor2 = trans.TransformDirection(normals[tris[i * 3 + 1]]);Vector3 nor3 = trans.TransformDirection(normals[tris[i * 3 + 2]]);//顶点变换到世界空间Vector3 worldPos1 = trans.TransformPoint(vertices[tris[i * 3]]);Vector3 worldPos2 = trans.TransformPoint(vertices[tris[i * 3 + 1]]);Vector3 worldPos3 = trans.TransformPoint(vertices[tris[i * 3 + 2]]);//如果需要从左手系变换到右手系if (exchangeCoordinate){nor1.x *= -1;nor2.x *= -1;nor3.x *= -1;worldPos1.x *= -1;worldPos2.x *= -1;worldPos3.x *= -1;}Vector3 normal = (nor1 + nor2 + nor3) / 3;sw.Write("\tfacet normal " + normal.x + " " + normal.y + " " + normal.z);sw.Write("\n\t\touter loop\n");sw.Write("\t\t\tvertex " + worldPos1.x + " " + worldPos1.y + " " + worldPos1.z + "\n");if (exchangeCoordinate){sw.Write("\t\t\tvertex " + worldPos3.x + " " + worldPos3.y + " " + worldPos3.z + "\n");sw.Write("\t\t\tvertex " + worldPos2.x + " " + worldPos2.y + " " + worldPos2.z + "\n");}else{sw.Write("\t\t\tvertex " + worldPos2.x + " " + worldPos2.y + " " + worldPos2.z + "\n");sw.Write("\t\t\tvertex " + worldPos3.x + " " + worldPos3.y + " " + worldPos3.z + "\n");}sw.Write("\t\tendloop\n");sw.Write("\tendfacet\n");}if (mesh.subMeshCount == 1){sw.Write("endsolid " + mesh.name);}else{sw.Write("endsolid " + mesh.name + "_" + j);}}}
- 二进制形式 将单个mesh写出为stl
/// <summary>/// 将单个mesh数据使用StreamWrite写出为stl,二进制格式/// </summary>/// <param name="mesh">待导出的mesh</param>/// <param name="bw">BinaryWriter 写出二进制数据的类</param>/// <param name="trans">mesh对应的transform,用于将顶点法线转到世界空间</param>/// <param name="exchangeCoordinate">是否需要变换坐标手系,unity是左手坐标系,默认变换到右手坐标系</param>private static void ExportMeshToStl(Mesh mesh, BinaryWriter bw, Transform trans, bool exchangeCoordinate = true){Vector3[] vertices = mesh.vertices;Vector3[] normals = mesh.normals;int[] tris = mesh.triangles;//每个三角面片固定占用50个字节for (int i = 0; i < tris.Length / 3; i++){Vector3 nor1 = trans.TransformDirection(normals[tris[i * 3]]);Vector3 nor2 = trans.TransformDirection(normals[tris[i * 3 + 1]]);Vector3 nor3 = trans.TransformDirection(normals[tris[i * 3 + 2]]);Vector3 worldPos1 = trans.TransformPoint(vertices[tris[i * 3]]);Vector3 worldPos2 = trans.TransformPoint(vertices[tris[i * 3 + 1]]);Vector3 worldPos3 = trans.TransformPoint(vertices[tris[i * 3 + 2]]);if (exchangeCoordinate){nor1.x *= -1;nor2.x *= -1;nor3.x *= -1;worldPos1.x *= -1;worldPos2.x *= -1;worldPos3.x *= -1;}Vector3 normal = (nor1 + nor2 + nor3) / 3;bw.Write(normal.x);bw.Write(normal.y);bw.Write(normal.z);bw.Write(worldPos1.x);bw.Write(worldPos1.y);bw.Write(worldPos1.z);if (exchangeCoordinate){bw.Write(worldPos3.x);bw.Write(worldPos3.y);bw.Write(worldPos3.z);bw.Write(worldPos2.x);bw.Write(worldPos2.y);bw.Write(worldPos2.z);}else{bw.Write(worldPos2.x);bw.Write(worldPos2.y);bw.Write(worldPos2.z);bw.Write(worldPos3.x);bw.Write(worldPos3.y);bw.Write(worldPos3.z);}//填充两个字节 三角面片的最后2个字节用来描述三角面片的属性信息(包括颜色属性等)暂时没有用bw.Seek(2, SeekOrigin.Current);}}
完整代码
/****************************************************文件:Exporter.cs作者:TKB邮箱: 544726237@qq.com日期:2021/7/24 23:9:12功能:导出stl
*****************************************************/using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using UnityEngine;namespace TLib
{public class Exporter{#region 导出stl/// <summary>/// 导出Transfrom及其子mesh为单个stl/// </summary>/// <param name="trans">待导出的transfrom</param>/// <param name="outputPath">导出的stl完整路径,如D:/TKB/output.stl</param>/// <param name="exchangeCoordinate">是否要变换坐标系,从左手坐标系(unity)变换到右手坐标系,默认为true</param>/// <param name="isBinary">是否以格式导出</param>public static void ExportStl(Transform trans, string outputPath, bool exchangeCoordinate = true, bool isBinary = true){ExportStl(trans.gameObject, outputPath, exchangeCoordinate, isBinary);}/// <summary>/// 导出GameObject及其子mesh为单个stl/// </summary>/// <param name="go">待导出的GameObject</param>/// <param name="outputPath">导出的stl完整路径,如D:/TKB/output.stl</param>/// <param name="exchangeCoordinate">是否要变换坐标系,从左手坐标系(unity)变换到右手坐标系,默认为true</param>/// <param name="isBinary">是否以格式导出</param>public static void ExportStl(GameObject go, string outputPath, bool exchangeCoordinate = true, bool isBinary = true){if (!go) return;if (!Directory.Exists(Path.GetDirectoryName(outputPath))){Directory.CreateDirectory(Path.GetDirectoryName(outputPath));}if (File.Exists(outputPath)){try{File.Delete(outputPath);Debug.LogWarning("该路径已存在同名文件,已删除!" + outputPath);}catch (Exception e){Debug.LogError(e + "该路径已存在同名文件并且删除失败!" + outputPath);return;}}MeshFilter[] meshFilters = go.GetComponentsInChildren<MeshFilter>();SkinnedMeshRenderer[] skinnedMeshRenderers = go.GetComponentsInChildren<SkinnedMeshRenderer>();int meshCount = meshFilters.Length + skinnedMeshRenderers.Length;try{FileStream meshFS = new FileStream(outputPath, FileMode.Create, FileAccess.Write, FileShare.ReadWrite); ;StreamWriter meshSW = null;BinaryWriter meshBW = null;if (!isBinary){meshSW = new StreamWriter(meshFS, Encoding.UTF8);}else{meshBW = new BinaryWriter(meshFS, Encoding.UTF8);//文件的起始80字节是文件头存储零件名,可以放入任何文字信息meshBW.Write(go.name);meshBW.Seek(80, SeekOrigin.Begin);//紧随着用4个字节的整数来描述实体的三角面片个数int count = 0;for (int i = 0; i < meshFilters.Length; i++){Mesh mesh;
#if UNITY_EDITORmesh = meshFilters[i].sharedMesh;#elsemesh = meshFilters[i].mesh;
#endifcount += mesh.triangles.Length;}for (int i = 0; i < skinnedMeshRenderers.Length; i++){Mesh mesh;
#if UNITY_EDITORmesh = skinnedMeshRenderers[i].sharedMesh;#elsemesh = meshFilters[i].mesh;
#endifcount += mesh.triangles.Length;}meshBW.Write(count/3);}for (int i = 0; i < meshFilters.Length; i++){Mesh mesh;
#if UNITY_EDITORmesh = meshFilters[i].sharedMesh;UnityEditor.EditorUtility.DisplayProgressBar("导出Stl", mesh.name + ":" + i + "/" + meshCount, i * 1.0f / meshCount);
#elsemesh = meshFilters[i].mesh;
#endifif (!isBinary)ExportMeshToStl(mesh, meshSW, meshFilters[i].transform, exchangeCoordinate);elseExportMeshToStl(mesh, meshBW, meshFilters[i].transform, exchangeCoordinate);}for (int i = 0; i < skinnedMeshRenderers.Length; i++){Mesh mesh;
#if UNITY_EDITORmesh = skinnedMeshRenderers[i].sharedMesh;UnityEditor.EditorUtility.DisplayProgressBar("导出Stl", mesh.name + ":" + (i + meshFilters.Length) + "/" + meshCount, i * 1.0f / meshCount);
#elsemesh = meshFilters[i].mesh;
#endifif (!isBinary)ExportMeshToStl(mesh, meshSW, skinnedMeshRenderers[i].transform, exchangeCoordinate);elseExportMeshToStl(mesh, meshBW, skinnedMeshRenderers[i].transform, exchangeCoordinate);}if (!isBinary){meshSW.Close();}else{meshBW.Close();}meshFS.Close();}catch (Exception e){Debug.LogError(e);}finally{UnityEditor.EditorUtility.ClearProgressBar();}}/// <summary>/// 将Transform及其子对象导出为多个stl,每个mesh对应一个/// </summary>/// <param name="trans">待导出的Transform</param>/// <param name="outputDir">导出的文件夹路径,stl存放的位置</param>/// <param name="exchangeCoordinate">是否要变换坐标系,从左手坐标系(unity)变换到右手坐标系,默认为true</param>/// <param name="isBinary">是否以格式导出</param>public static void ExportStls(Transform trans, string outputDir, bool exchangeCoordinate = true, bool isBinary = true){ExportStls(trans.gameObject, outputDir, exchangeCoordinate, isBinary);}/// <summary>/// 将GameObject及其子对象导出为多个stl,每个mesh对应一个/// </summary>/// <param name="go">待导出的GameObject</param>/// <param name="outputDir">导出的文件夹路径,stl存放的位置</param>/// <param name="exchangeCoordinate">是否要变换坐标系,从左手坐标系(unity)变换到右手坐标系,默认为true</param>/// <param name="isBinary">是否以格式导出</param>public static void ExportStls(GameObject go, string outputDir, bool exchangeCoordinate = true, bool isBinary = true){if (!Directory.Exists(outputDir)) Directory.CreateDirectory(outputDir);MeshFilter[] meshFilters = go.GetComponentsInChildren<MeshFilter>();SkinnedMeshRenderer[] skinnedMeshRenderers = go.GetComponentsInChildren<SkinnedMeshRenderer>();Dictionary<string, int> meshNameDic = new Dictionary<string, int>();int meshCount = meshFilters.Length + skinnedMeshRenderers.Length;for (int i = 0; i < meshFilters.Length; i++){try{string name = meshFilters[i].gameObject.name;if (meshNameDic.ContainsKey(name)){meshNameDic[name]++;name += meshNameDic[name];}else meshNameDic.Add(name, 0);string stlPath = Path.Combine(outputDir, name + ".stl");FileStream meshFS = new FileStream(stlPath, FileMode.Create, FileAccess.Write, FileShare.ReadWrite);StreamWriter meshSW = null;BinaryWriter meshBW = null;Mesh mesh;
#if UNITY_EDITORmesh = meshFilters[i].sharedMesh;UnityEditor.EditorUtility.DisplayProgressBar("导出Stl", mesh.name + ":" + i + "/" + meshCount, i * 1.0f / meshCount);
#elsemesh = meshFilters[i].mesh;
#endifif (!isBinary){meshSW = new StreamWriter(meshFS, Encoding.UTF8);ExportMeshToStl(mesh, meshSW, meshFilters[i].transform, exchangeCoordinate);meshSW.Close();}else{meshBW = new BinaryWriter(meshFS, Encoding.UTF8);//文件的起始80字节是文件头存储零件名,可以放入任何文字信息meshBW.Write(name);meshBW.Seek(80, SeekOrigin.Begin);meshBW.Write(mesh.triangles.Length / 3);ExportMeshToStl(mesh, meshBW, meshFilters[i].transform, exchangeCoordinate);meshBW.Close();}meshFS.Close();}catch (Exception e){Debug.LogError(e);}}for (int i = 0; i < skinnedMeshRenderers.Length; i++){try{string name = skinnedMeshRenderers[i].gameObject.name;if (meshNameDic.ContainsKey(name)){name += meshNameDic[name];meshNameDic[name]++;}else meshNameDic.Add(name, 1);string stlPath = Path.Combine(outputDir, name + ".stl");FileStream meshFS = new FileStream(stlPath, FileMode.Create, FileAccess.Write, FileShare.ReadWrite);StreamWriter meshSW = null;BinaryWriter meshBW = null;Mesh mesh;
#if UNITY_EDITORmesh = skinnedMeshRenderers[i].sharedMesh;UnityEditor.EditorUtility.DisplayProgressBar("导出Stl", mesh.name + ":" + (i + meshFilters.Length) + "/" + meshCount, i * 1.0f / meshCount);
#elsemesh = meshFilters[i].mesh;
materials;
#endifif (!isBinary){meshSW = new StreamWriter(meshFS, Encoding.UTF8);ExportMeshToStl(mesh, meshSW, skinnedMeshRenderers[i].transform, exchangeCoordinate);meshSW.Close();}else{meshBW = new BinaryWriter(meshFS, Encoding.UTF8);//文件的起始80字节是文件头存储零件名,可以放入任何文字信息meshBW.Write(name);meshBW.Seek(80, SeekOrigin.Begin);meshBW.Write(mesh.triangles.Length / 3);ExportMeshToStl(mesh, meshBW, skinnedMeshRenderers[i].transform, exchangeCoordinate);meshBW.Close();}meshFS.Close();}catch (Exception e){Debug.LogError(e);}}UnityEditor.EditorUtility.ClearProgressBar();}/// <summary>/// 将单个mesh数据使用StreamWrite写出为stl/// </summary>/// <param name="mesh">待导出的mesh</param>/// <param name="sw">输出流</param>/// <param name="trans">mesh对应的transform,用于将顶点法线转到世界空间</param>/// <param name="exchangeCoordinate">是否需要变换坐标手系,unity是左手坐标系,默认变换到右手坐标系</param>private static void ExportMeshToStl(Mesh mesh, StreamWriter sw, Transform trans, bool exchangeCoordinate = true){for (int j = 0; j < mesh.subMeshCount; j++){int[] tris;if (mesh.subMeshCount == 1){sw.Write("\nsolid " + mesh.name + "\n");tris = mesh.triangles;}else{sw.Write("\nsolid " + mesh.name + "_" + j + "\n");tris = mesh.GetIndices(j);}Vector3[] vertices = mesh.vertices;Vector3[] normals = mesh.normals;for (int i = 0; i < tris.Length / 3; i++){Vector3 nor1 = trans.TransformDirection(normals[tris[i * 3]]);Vector3 nor2 = trans.TransformDirection(normals[tris[i * 3 + 1]]);Vector3 nor3 = trans.TransformDirection(normals[tris[i * 3 + 2]]);Vector3 worldPos1 = trans.TransformPoint(vertices[tris[i * 3]]);Vector3 worldPos2 = trans.TransformPoint(vertices[tris[i * 3 + 1]]);Vector3 worldPos3 = trans.TransformPoint(vertices[tris[i * 3 + 2]]);if (exchangeCoordinate){nor1.x *= -1;nor2.x *= -1;nor3.x *= -1;worldPos1.x *= -1;worldPos2.x *= -1;worldPos3.x *= -1;}Vector3 normal = (nor1 + nor2 + nor3) / 3;sw.Write("\tfacet normal " + normal.x + " " + normal.y + " " + normal.z);sw.Write("\n\t\touter loop\n");sw.Write("\t\t\tvertex " + worldPos1.x + " " + worldPos1.y + " " + worldPos1.z + "\n");if (exchangeCoordinate){sw.Write("\t\t\tvertex " + worldPos3.x + " " + worldPos3.y + " " + worldPos3.z + "\n");sw.Write("\t\t\tvertex " + worldPos2.x + " " + worldPos2.y + " " + worldPos2.z + "\n");}else{sw.Write("\t\t\tvertex " + worldPos2.x + " " + worldPos2.y + " " + worldPos2.z + "\n");sw.Write("\t\t\tvertex " + worldPos3.x + " " + worldPos3.y + " " + worldPos3.z + "\n");}sw.Write("\t\tendloop\n");sw.Write("\tendfacet\n");}if (mesh.subMeshCount == 1){sw.Write("endsolid " + mesh.name);}else{sw.Write("endsolid " + mesh.name + "_" + j);}}}/// <summary>/// 将单个mesh数据使用StreamWrite写出为stl,二进制格式/// </summary>/// <param name="mesh">待导出的mesh</param>/// <param name="bw">BinaryWriter 写出二进制数据的类</param>/// <param name="trans">mesh对应的transform,用于将顶点法线转到世界空间</param>/// <param name="exchangeCoordinate">是否需要变换坐标手系,unity是左手坐标系,默认变换到右手坐标系</param>private static void ExportMeshToStl(Mesh mesh, BinaryWriter bw, Transform trans, bool exchangeCoordinate = true){Vector3[] vertices = mesh.vertices;Vector3[] normals = mesh.normals;int[] tris = mesh.triangles;//每个三角面片固定占用50个字节for (int i = 0; i < tris.Length / 3; i++){Vector3 nor1 = trans.TransformDirection(normals[tris[i * 3]]);Vector3 nor2 = trans.TransformDirection(normals[tris[i * 3 + 1]]);Vector3 nor3 = trans.TransformDirection(normals[tris[i * 3 + 2]]);Vector3 worldPos1 = trans.TransformPoint(vertices[tris[i * 3]]);Vector3 worldPos2 = trans.TransformPoint(vertices[tris[i * 3 + 1]]);Vector3 worldPos3 = trans.TransformPoint(vertices[tris[i * 3 + 2]]);if (exchangeCoordinate){nor1.x *= -1;nor2.x *= -1;nor3.x *= -1;worldPos1.x *= -1;worldPos2.x *= -1;worldPos3.x *= -1;}Vector3 normal = (nor1 + nor2 + nor3) / 3;bw.Write(normal.x);bw.Write(normal.y);bw.Write(normal.z);bw.Write(worldPos1.x);bw.Write(worldPos1.y);bw.Write(worldPos1.z);if (exchangeCoordinate){bw.Write(worldPos3.x);bw.Write(worldPos3.y);bw.Write(worldPos3.z);bw.Write(worldPos2.x);bw.Write(worldPos2.y);bw.Write(worldPos2.z);}else{bw.Write(worldPos2.x);bw.Write(worldPos2.y);bw.Write(worldPos2.z);bw.Write(worldPos3.x);bw.Write(worldPos3.y);bw.Write(worldPos3.z);}//填充两个字节 三角面片的最后2个字节用来描述三角面片的属性信息(包括颜色属性等)暂时没有用bw.Seek(2, SeekOrigin.Current);}}}#endregion
}
测试脚本
/****************************************************文件:ExportStlExample.cs作者:TKB邮箱: 544726237@qq.com日期:2021/7/26 22:19:56功能:编辑器环境测试将选中的物体导出stl
*****************************************************/using UnityEngine;namespace TLib
{public class ExportStlExample{
#if UNITY_EDITOR//将当前选中的物体下所有mesh导出到一个stl中[UnityEditor.MenuItem("Tools/导出stl", false)]private static void OnClickExportObj(){GameObject go = UnityEditor.Selection.activeObject as GameObject;Exporter.ExportStl(go.transform, Application.dataPath +"/"+ go.name+".stl",true,false);UnityEditor.AssetDatabase.Refresh();}//将当前选中的物体下的mesh分别导出为stl[UnityEditor.MenuItem("Tools/导出stls", false)]private static void OnClickExportObj1(){GameObject go = UnityEditor.Selection.activeObject as GameObject;Exporter.ExportStls(go, Application.dataPath + "/Exports");UnityEditor.AssetDatabase.Refresh();}
#endif}
}
效果
unity中的模型截图:
选择导出为stl 在meshlab中的截图:
选择导出为stls时导出了3000+的模型:
注意
这个测试模型导出二进制格式时使用meshlab打开报错,但是用CAD Assistant可以打开,原因还不清楚
unity 导出 stl相关推荐
- Unity导出apk出现的问题,JDK,Android SDK,NDK,无“安装模块”
导出apk失败 使用unity导出apk文件,会出现提示:需要合适版本的JDK.Android SDK和Android NDK,要找到.下载和安装好合适的版本非常耗费时间, 网上很多教程指出可以直接在 ...
- unity导出工程导入到iOS原生工程中详细步骤
一直想抽空整理一下unity原生工程导入iOS原生工程中的详细步骤.做iOS+vuforia+unity开发这么长时间了.从最初的小小白到现在的小白.中间趟过了好多的坑.也有一些的小小收货.做一个喜欢 ...
- html文件怎么导出stl文件,各种3D建模软件导出STL文件的小技巧(一)
很多用户在提交3D模型文件的时候,常常有这样的困惑:什么是STL 格式文件,怎么获取STL 格式文件呢?STL 格式文件是在计算机图形应用系统中,用于表示三角形网格的一种文件格式.它也是3D打印机在执 ...
- html文件怎么导出stl文件,3D建模软件导出STL文件的小技巧(一)
很多用户在提交3D模型文件的时候,常常有这样的困惑:什么是STL 格式文件,怎么获取STL 格式文件呢?STL 格式文件是在计算机图形应用系统中,用于表示三角形网格的一种文件格式.它也是3D打印机在执 ...
- Egret3D初步笔记二 (Unity导出场景使用)
一 Scene 根据上一节的继续.在导入unity4.7.1_Egret3D_Dll.unitypackage后. 在Unity中双击打开Assets/Egret3D/Example下的Example ...
- unity 发布苹果商店_[Mac] Unity 导出 iOS 游戏并上架 App Store
unity_to_appstore.jpg 0. 前言 因为之前已经上架过一款 App(Swift �语言),所以开发者账号.证书这些都已经搞定了,如果你是第一次上架 iOS 应用,具体流程可以参考本 ...
- Unity导出微信小游戏
微信小游戏感觉这几年挺火,打算熟悉一下流程看看 微信提供的Unity转微信小游戏解决方案 地址:https://developers.weixin.qq.com/minigame/dev/guide/ ...
- Unity导出模型为Obj文件
Unity导出模型为Obj文件 资源链接 下载导入 代码纪要 使用方式 参考链接 资源链接 原插件代码中只有MeshFilter的Obj导出代码:由于项目需求,需要将SkinnedMeshRender ...
- unity导出.obj模型文件
unity导出.obj模型文件 最近使用realworldterrain生成真实地形遇到一个问题,就是该地形的坐标轴没有在中心位置,这样在旋转缩放操作时候就有各种问题,效果不好,于是想到先导出该地形为 ...
- Unity 导出 obj, fbx
本文转自本人简书,原文链接: https://www.jianshu.com/p/6b7e36f70be3 2020-05-05 项目需要用Unity导出3D物体为obj或fbx格式,从而导入其他软件 ...
最新文章
- Android中removeCallbacks失效原因
- php中location.reload,js刷新页面location.reload()用法详解
- Android进阶笔记:AIDL内部实现详解 (二)
- dft变换的两幅图_快速傅里叶变换FFT计算方法 原理及公式
- 关于VMware虚拟机安装windows 7系统
- UWP 开发初阶 Chapter 6 - 简单介绍如何使用 C# 改变 XAML 控件的属性
- 院士新作赠送——调查问卷活动感谢信
- (操作系统题目题型总结)第五章:设备管理
- TypeScript1---数据类型和函数
- laypage分页java例子_layPage分页示例
- 项目管理(软件开发)之甘特图使用
- python字符画绘制代码_python图片转字符画代码是什么
- 使用VNC远程登录百度智能云服务器
- python打印上下标
- STM32毕业设计题目大全
- singleton pattern的一个模板实现, 适用于单线程, 并且提供了Release方法
- Mac电脑查看本机的mac地址和ip地址
- Google analytics是什么,有什么作用
- python解析mht文件_php解析mht文件转换成html的实例详解
- Java实现蓝桥杯G将军
热门文章
- 用图818“女版乔布斯”霍姆斯定罪前后的轨迹
- Cisco交换机IOS升级
- 虚拟机安装win10 x64系统
- java输出华氏摄氏温度转换表_输出华氏-摄氏温度转换表
- Android Studio模拟器安装步骤
- VBA 字典 键值为二维数组并不断增加行
- 汇编:根据段大小计算偏移地址
- 【CVPR2022】论文阅读:Revisiting Skeleton-based Action Recognition
- 信息加工心理学用计算机的工作原理,第四章 认知学习理论 第七节 信息加工学习理论...
- c语言编程模拟银行取钱代码,C语言 用初等函数模拟银行取款