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相关推荐

  1. Unity导出apk出现的问题,JDK,Android SDK,NDK,无“安装模块”

    导出apk失败 使用unity导出apk文件,会出现提示:需要合适版本的JDK.Android SDK和Android NDK,要找到.下载和安装好合适的版本非常耗费时间, 网上很多教程指出可以直接在 ...

  2. unity导出工程导入到iOS原生工程中详细步骤

    一直想抽空整理一下unity原生工程导入iOS原生工程中的详细步骤.做iOS+vuforia+unity开发这么长时间了.从最初的小小白到现在的小白.中间趟过了好多的坑.也有一些的小小收货.做一个喜欢 ...

  3. html文件怎么导出stl文件,各种3D建模软件导出STL文件的小技巧(一)

    很多用户在提交3D模型文件的时候,常常有这样的困惑:什么是STL 格式文件,怎么获取STL 格式文件呢?STL 格式文件是在计算机图形应用系统中,用于表示三角形网格的一种文件格式.它也是3D打印机在执 ...

  4. html文件怎么导出stl文件,3D建模软件导出STL文件的小技巧(一)

    很多用户在提交3D模型文件的时候,常常有这样的困惑:什么是STL 格式文件,怎么获取STL 格式文件呢?STL 格式文件是在计算机图形应用系统中,用于表示三角形网格的一种文件格式.它也是3D打印机在执 ...

  5. Egret3D初步笔记二 (Unity导出场景使用)

    一 Scene 根据上一节的继续.在导入unity4.7.1_Egret3D_Dll.unitypackage后. 在Unity中双击打开Assets/Egret3D/Example下的Example ...

  6. unity 发布苹果商店_[Mac] Unity 导出 iOS 游戏并上架 App Store

    unity_to_appstore.jpg 0. 前言 因为之前已经上架过一款 App(Swift �语言),所以开发者账号.证书这些都已经搞定了,如果你是第一次上架 iOS 应用,具体流程可以参考本 ...

  7. Unity导出微信小游戏

    微信小游戏感觉这几年挺火,打算熟悉一下流程看看 微信提供的Unity转微信小游戏解决方案 地址:https://developers.weixin.qq.com/minigame/dev/guide/ ...

  8. Unity导出模型为Obj文件

    Unity导出模型为Obj文件 资源链接 下载导入 代码纪要 使用方式 参考链接 资源链接 原插件代码中只有MeshFilter的Obj导出代码:由于项目需求,需要将SkinnedMeshRender ...

  9. unity导出.obj模型文件

    unity导出.obj模型文件 最近使用realworldterrain生成真实地形遇到一个问题,就是该地形的坐标轴没有在中心位置,这样在旋转缩放操作时候就有各种问题,效果不好,于是想到先导出该地形为 ...

  10. Unity 导出 obj, fbx

    本文转自本人简书,原文链接: https://www.jianshu.com/p/6b7e36f70be3 2020-05-05 项目需要用Unity导出3D物体为obj或fbx格式,从而导入其他软件 ...

最新文章

  1. Android中removeCallbacks失效原因
  2. php中location.reload,js刷新页面location.reload()用法详解
  3. Android进阶笔记:AIDL内部实现详解 (二)
  4. dft变换的两幅图_快速傅里叶变换FFT计算方法 原理及公式
  5. 关于VMware虚拟机安装windows 7系统
  6. UWP 开发初阶 Chapter 6 - 简单介绍如何使用 C# 改变 XAML 控件的属性
  7. 院士新作赠送——调查问卷活动感谢信
  8. (操作系统题目题型总结)第五章:设备管理
  9. TypeScript1---数据类型和函数
  10. laypage分页java例子_layPage分页示例
  11. 项目管理(软件开发)之甘特图使用
  12. python字符画绘制代码_python图片转字符画代码是什么
  13. 使用VNC远程登录百度智能云服务器
  14. python打印上下标
  15. STM32毕业设计题目大全
  16. singleton pattern的一个模板实现, 适用于单线程, 并且提供了Release方法
  17. Mac电脑查看本机的mac地址和ip地址
  18. Google analytics是什么,有什么作用
  19. python解析mht文件_php解析mht文件转换成html的实例详解
  20. Java实现蓝桥杯G将军

热门文章

  1. 用图818“女版乔布斯”霍姆斯定罪前后的轨迹
  2. Cisco交换机IOS升级
  3. 虚拟机安装win10 x64系统
  4. java输出华氏摄氏温度转换表_输出华氏-摄氏温度转换表
  5. Android Studio模拟器安装步骤
  6. VBA 字典 键值为二维数组并不断增加行
  7. 汇编:根据段大小计算偏移地址
  8. 【CVPR2022】论文阅读:Revisiting Skeleton-based Action Recognition
  9. 信息加工心理学用计算机的工作原理,第四章 认知学习理论 第七节 信息加工学习理论...
  10. c语言编程模拟银行取钱代码,C语言 用初等函数模拟银行取款