Unity开发-3D切片开发历程

开发一个项目,需要将3d打印的STL类型的模型进行类似于切片操作。

具体要求如下:

对使用Solidworks等软件生产的STL文件进行处理,生成方便进行3D打印的格式。

  • 首先要求能够导入需要打印的STL文件;
  • 其次要求能够对STL模型进行切片,可以置切片层间距;
  • 按照要求的图片格式生产每层切片的PNG图像;

导入STL模型

由于Untiy本身不支持STL模型,并且unity的一个mesh最多只能支持65000面,因此正常人也不会用Unity来开发STL文件(我也觉得很傻逼)。试了几个CSDN上的代码,bug千奇百怪(CSDN纯废物)。最后的解决方案是在UnityStore上面买了一个STL导入插件,叫Runtime STL Loader。

STL模型进行切片效果模拟

一开始的设计思路是想着按照字面意思对模型进行切片,也做了Demo发给老师看,但是后面跟老师沟通后觉得直接切片会有问题。原因是切片出来的物体不会自动消失,影响拍照,其次切出的网格可能会发生变化导致模型变形(每次切片后,切片接触面需要重新生成网格不然会形成一个空腔)。

因此打算采用类似于磨皮的方式来体现出切片的项目,使用的插件为Unity3DCrossSectionShader,UnityStore上的文件已经下架,建议在Github上下载:github.com/Dandarawy/Unity3DCrossSectionShader

Unity3DCrossSectionShader具体实现实现后面开个单章来解说,简而言之,获取一个物体的XYZ轴向量,组成的一个平面,利用Stencil缓冲区和Cull设置,剔除超出平面的部分,并且独绘制裁切面的截面颜色。如同上图第一排所示。

通过它可以实现物体从无到有的一个类似于3d的打印过程,适合拍片再进行打印。

拍照处理

前面说到,需要对模型切片后的效果进行拍照导出,这一块内容较为简单。根据老师的要求,画面只有黑白两种颜色。因此我们需要对摄像机和天空盒进行处理。

摄像机

思路就是新建一个摄像机,主摄像机只负责看,后续代码基本跟主摄像机无关。

  • ClearFlags设置成soliderColor,颜色纯黑。
  • 重点就是将Projection的模式设置成Orthographic,避免产生近大远小的问题。
  • 在文件夹新建一个Render Texture,分辨率设置1980*1080,挂载摄像机上。

天空盒

摄像机拍摄的图片只能有黑白两色

  • 场景里的光源关掉(在运行的时候代码隐藏)。
  • Window->Light(ctrl+9)打开灯光设置,按照下述参考配置。

这样下来摄像机就能拍出一张黑白照(建议直接拍熊猫)

开始切片

这一块内容同样不难,根据Unity3DCrossSectionShader的原理,我们需要利用切片平面的Y轴,设置移动距离,也就是切片层间距。每移动一次,就拍一张照。并将拍的的照片保存到指定文件夹。这样我们最基础的功能-切片模拟就完成了。

        RenderTexture rt = captureCamera.targetTexture;
        captureCamera.clearFlags = CameraClearFlags.SolidColor;
        captureCamera.backgroundColor = Color.black;

        Texture2D screenShot = new Texture2D(rt.width, rt.height, TextureFormat.RGB24, false);
        captureCamera.Render();

        RenderTexture.active = rt;
        screenShot.ReadPixels(new Rect(0, 0, rt.width, rt.height), 0, 0);
        screenShot.Apply();

1. 获取目标渲染纹理

RenderTexture rt = captureCamera.targetTexture;
  • captureCamera 是一个 Camera 对象。
  • targetTexture 指定了摄像机的目标渲染纹理 (RenderTexture)。
  • 这里通过 targetTexture 获取摄像机的渲染目标纹理,后续会用来读取渲染结果。

2. 设置摄像机的清屏方式和背景色

captureCamera.clearFlags = CameraClearFlags.SolidColor;
captureCamera.backgroundColor = Color.black;
  • clearFlags 定义了摄像机在每次渲染前如何清除背景:
    • CameraClearFlags.SolidColor 表示用单一颜色填充屏幕背景。
  • backgroundColor 定义了清屏时填充的颜色,这里是黑色。

3. 创建目标图片的存储容器

Texture2D screenShot = new Texture2D(rt.width, rt.height, TextureFormat.RGB24, false);
  • 创建一个 Texture2D 对象,用来存储渲染纹理的数据。
  • 参数解释:
    • rt.widthrt.height:图片的宽度和高度,与渲染纹理一致。
    • TextureFormat.RGB24:指定图片的格式为 RGB,不包括 Alpha 通道(每像素 24 位)。
    • false:不生成 mipmaps(多级细化纹理)。

4. 触发摄像机渲染

captureCamera.Render();
  • 手动调用摄像机的 Render 方法,执行一次完整的场景渲染流程。
  • 渲染结果会写入目标 RenderTexture

5. 激活目标渲染纹理

RenderTexture.active = rt;
  • 将指定的 RenderTexture 设置为当前活动的渲染目标。
  • 这是为了使后续操作能够直接访问 RenderTexture 的像素数据。

6. 从渲染纹理中读取像素

screenShot.ReadPixels(new Rect(0, 0, rt.width, rt.height), 0, 0);
screenShot.Apply();
  • ReadPixels 从当前激活的渲染纹理中读取指定矩形区域的像素数据,存储到 Texture2D 中。
    • new Rect(0, 0, rt.width, rt.height):指定读取的区域,从左下角 (0,0) 开始,宽度和高度为 rt 的尺寸。
    • 0, 0:目标 Texture2D 的写入起点。
  • screenShot.Apply() 应用读取的像素数据,使其生效。

结论

Unity 开发上位机并非适用于所有场景,例如本次Unity导入STL模型的问题,也是花了功夫来研究怎么导入STL,最终也还是感谢有人开发了导入插件,不如都不知道怎么进行下一步。对于后面的图像处理很多都可以通过GPT来进行功能定制,Unity在这块还是有它的生态的。

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇