mesh导出OBJ、STL格式和win窗口调用

这篇具有很好参考价值的文章主要介绍了mesh导出OBJ、STL格式和win窗口调用。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

背景:客户想在UG中打开编辑好的模型,UG不支持obj格式。mesh转曲面不太现实,折中取了个STL。

mesh转OBJ格式

设置导出模型的零点,例如设置底面中心为导出模型的零点。

        float offsetX = 0;
        float offsetY = 0;
        float offsetZ = 0;
        float minX = float.MaxValue;
        float maxX = float.MinValue;
        float minY = float.MaxValue;
        float maxY = float.MinValue;
        float minZ = float.MaxValue;
        float maxZ = float.MinValue;   
        foreach (var item in vertices )
        {
            Vector3 worldPos = trans.TransformPoint(item);
            if (minX > worldPos.x) minX = worldPos.x;
            if (minY > worldPos.y) minY = worldPos.y;
            if (minZ > worldPos.z) minZ = worldPos.z;
            if (maxX < worldPos.x) maxX = worldPos.x;
            if (maxY < worldPos.y) maxY = worldPos.y;
            if (maxZ < worldPos.z) maxZ = worldPos.z;
        }  
        offsetX = (minX + manX) / 2;
        offsetZ = (maxZ + minZ) / 2;
        offsetY = minY;

校验传入路径名称是否带.obj后缀。

   if (!name.Contains(".obj"))
        {
            name = Path.Combine(name + ".obj");
        }       

验证是否导出成功

  if (!File.Exists(name ))
        {
            UnityEngine.Debug.LogError("导出失败!");
        }

完整代码

  public static void Export(Transform trans, Mesh mesh, string name)
    {
        if (mesh == null) return;
        Vector3[] vertices = mesh.vertices;
        Vector3[] normals = mesh.normals;
        int[] triangles = mesh.triangles;
        StringBuilder sb = new StringBuilder();
        float offsetX = 0;
        float offsetY = 0;
        float offsetZ = 0;
        float minX = float.MaxValue;
        float maxX = float.MinValue;
        float minY = float.MaxValue;
        float maxY = float.MinValue;
        float minZ = float.MaxValue;
        float maxZ = float.MinValue;         

        foreach (var item in vertices )
        {
            Vector3 worldPos = trans.TransformPoint(item);
            if (minX > worldPos.x) minX = worldPos.x;
            if (minY > worldPos.y) minY = worldPos.y;
            if (minZ > worldPos.z) minZ = worldPos.z;
            if (maxX < worldPos.x) maxX = worldPos.x;
            if (maxY < worldPos.y) maxY = worldPos.y;
            if (maxZ < worldPos.z) maxZ = worldPos.z;
        }

        offsetX = minX;
        offsetZ = (maxZ + minZ) / 2;
        offsetY = (minY + maxY) / 2;
       

        //sb.Append("#为模型导出的obj,不带材质\n\n");     
        for (int i = 0; i < vertices.Length; i++)
        {
            Vector3 worldVertices = trans.TransformPoint(vertices[i]);
            sb.Append("v " + (worldVertices.x - offsetX) + " " + (worldVertices.y - offsetY) + " " + (worldVertices.z - offsetZ) + "\n");
        }
        sb.Append("\n");

        for (int i = 0; i < normals.Length; i++)
        {
            //反转法线过后
            sb.Append("vn " + -(normals[i].y) + " " + (normals[i].x) + " " + (normals[i].z) + "\n");
        }
        sb.Append("\n");

        for (int i = 0; i < triangles.Length; i += 3)
        {
            sb.Append("f " + (triangles[i] + 1) + "//" + (triangles[i] + 1) + " " + (triangles[i+1] + 1) + "//" + (triangles[i+1] + 1) + " " + (triangles[i + 2] + 1) + "//" + (triangles[i + 2] + 1) + "\n");
        }
//校验导出名称
        if (!name.Contains(".obj"))
        {
            name = Path.Combine(name + ".obj");
        }       
        File.WriteAllText(name, sb.ToString());
        if (!File.Exists(name ))
        {
            UnityEngine.Debug.LogError("导出失败!");
        }
    }

mesh转STL格式

二进制格式(UG打开正常)

 public static void STLExportBinary(Transform trans,, Mesh mesh, string name)
    {
        if (mesh == null) return;
        Vector3[] vertices = mesh.vertices;
        Vector3[] normals = mesh.normals;
        int[] triangles = mesh.triangles;
        StringBuilder sb = new StringBuilder();
        float offsetX = 0;
        float offsetY = 0;
        float offsetZ = 0;
        float minX = float.MaxValue;
        float maxX = float.MinValue;
        float minY = float.MaxValue;
        float maxY = float.MinValue;
        float minZ = float.MaxValue;
        float maxZ = float.MinValue;         

        foreach (var item in vertices )
        {
            Vector3 worldPos = trans.TransformPoint(item);
            if (minX > worldPos.x) minX = worldPos.x;
            if (minY > worldPos.y) minY = worldPos.y;
            if (minZ > worldPos.z) minZ = worldPos.z;
            if (maxX < worldPos.x) maxX = worldPos.x;
            if (maxY < worldPos.y) maxY = worldPos.y;
            if (maxZ < worldPos.z) maxZ = worldPos.z;
        }

        offsetX = minX;
        offsetZ = (maxZ + minZ) / 2;
        offsetY = (minY + maxY) / 2;
         int trianglesCount = triangles.Length;

        //计算出stl的大小

        int stlSize = 80 + 4 + (trianglesCount + 360) * (4 * 12 + 2);

        byte[] stl = new byte[stlSize];

        //创建一个文件流用于将数据写入到本地

        MemoryStream ms = new MemoryStream(stl);

        BinaryWriter writer = new BinaryWriter(ms);

        byte[] header = new byte[80];

        short _short = 0;



        header[0] = 73;

        header[1] = 99;

        header[2] = 101;

        header[3] = 109;

        header[4] = 97;

        header[5] = 110;

        writer.Write(header);

        writer.Write(trianglesCount);

        //循环遍历顶点,并将数据写入到文件中

        for (int i = 0; i < trianglesCount; i += 3)

        {
                    writer.Write(0.0f);

                    writer.Write(0.0f);

                    writer.Write(0.0f);

                    Vector3 worldPos1 = (vertices[triangles[i]]) ;
                    Vector3 worldPos2 = (vertices[triangles[i + 2]]) ;
                    Vector3 worldPos3 = (vertices[triangles[i + 1]]);
                    writer.Write(worldPos1.x-offsetX );

                    writer.Write(worldPos1.z-offsetZ );

                    writer.Write(worldPos1.y-offsetY );



                    writer.Write(worldPos2.x-offsetX );

                    writer.Write(worldPos2.z-offsetZ );

                    writer.Write(worldPos2.y-offsetY );



                    writer.Write(worldPos3.x-offsetX );

                    writer.Write(worldPos3.z-offsetZ );

                    writer.Write(worldPos3.y-offsetY );

       
                    writer.Write(_short);
            
        }
        writer.Close();

        ms.Close();

        ms.Dispose();

        //将数据保存到本地

        File.WriteAllBytes(name , stl);


        if (!File.Exists(name))
        {
            UnityEngine.Debug.LogError("导出失败!");
        }
        else
        {
            UnityEngine.Debug.Log("导出完成");
          
        }

ASCII格式(UG打开报错)

基础框架和导出obj一致,区别在于写入了大量的标志信息。

  public static void STLExportASCII(Transform trans, Mesh mesh, string name)
    {  
        if (mesh == null) return;
        Vector3[] vertices = mesh.vertices;
        Vector3[] normals = mesh.normals;
        int[] triangles = mesh.triangles;
        StringBuilder sb = new StringBuilder();
        float offsetX = 0;
        float offsetY = 0;
        float offsetZ = 0;
        float minX = float.MaxValue;
        float maxX = float.MinValue;
        float minY = float.MaxValue;
        float maxY = float.MinValue;
        float minZ = float.MaxValue;
        float maxZ = float.MinValue;         

        foreach (var item in vertices )
        {
            Vector3 worldPos = trans.TransformPoint(item);
            if (minX > worldPos.x) minX = worldPos.x;
            if (minY > worldPos.y) minY = worldPos.y;
            if (minZ > worldPos.z) minZ = worldPos.z;
            if (maxX < worldPos.x) maxX = worldPos.x;
            if (maxY < worldPos.y) maxY = worldPos.y;
            if (maxZ < worldPos.z) maxZ = worldPos.z;
        }

        offsetX = minX;
        offsetZ = (maxZ + minZ) / 2;
        offsetY = (minY + maxY) / 2;
       
       sb.Append("\nsolid " + "导出工件" + "\n");
         for (int i = 0; i < triangles.Length / 3; i++)
        {
            try
            {
                Vector3 curPos1 = vertices[triangles[i * 3]];
                Vector3 curPos2 = vertices[triangles[i * 3 + 1]];
                Vector3 curPos3 = vertices[triangles[i * 3 + 2]];
               
                 
                        Vector3 nor1 = trans.TransformDirection(normals[triangles[i * 3]]);
                        Vector3 nor2 = trans.TransformDirection(normals[triangles[i * 3 + 1]]);
                        Vector3 nor3 = trans.TransformDirection(normals[triangles[i * 3 + 2]]);
                        //顶点变换到世界空间
                        Vector3 worldPos1 = trans.TransformPoint(curPos1);
                        Vector3 worldPos2 = trans.TransformPoint(curPos2);
                        Vector3 worldPos3 = trans.TransformPoint(curPos3);

                        Vector3 normal = (nor1 + nor2 + nor3) / 3;
                        sb.Append("facet normal " + normal.x + " " + normal.y + " " + normal.z);
                        sb.Append("outer loop\n");

                        sb.Append("\tvertex " + worldPos1.x-offsetX  + " " + worldPos1.y-offsetY + " " + worldPos1.z-offsetZ  + "\n");

                        sb.Append("\tvertex " + worldPos2.x-offsetX  + " " + worldPos2.y-offsetY + " " + worldPos2.z-offsetZ  + "\n");
                        sb.Append("\tvertex " + worldPos3.x -offsetX + " " + worldPos3.y-offsetY + " " + worldPos3.z-offsetZ  + "\n");

                        sb.Append("\tendloop\n");
                        sb.Append("\tendfacet\n");               
            }
            catch (Exception e)
            {
                UnityEngine.Debug.Log("缺少顶点重用信息,索引为:" + triangles[i * 3] + "\n" + e);
            }
        }
        sb.Append("endsolid " + name);
        File.WriteAllText(name, sb.ToString());
        if (!File.Exists(name))
        {
            UnityEngine.Debug.LogError("导出失败!");
        }
        else
        {
            UnityEngine.Debug.Log("导出完成");       
        }

调用win窗口

调用dll及基础参数定义,直接拷贝就行。

public class OpenFileName
{
    public int structSize = 0;
    public IntPtr dlgOwner = IntPtr.Zero;
    public IntPtr instance = IntPtr.Zero;
    public String filter = null;
    public String customFilter = null;
    public int maxCustFilter = 0;
    public int filterIndex = 0;
    public String file = null;
    public int maxFile = 0;
    public String fileTitle = null;
    public int maxFileTitle = 0;
    public String initialDir = null;
    public String title = null;
    public int flags = 0;
    public short fileOffset = 0;
    public short fileExtension = 0;
    public String defExt = null;
    public IntPtr custData = IntPtr.Zero;
    public IntPtr hook = IntPtr.Zero;
    public String templateName = null;
    public IntPtr reservedPtr = IntPtr.Zero;
    public int reservedInt = 0;
    public int flagsEx = 0;
}
///2.系统函数调用类, 如下:
public class LocalDialog
{
    //链接指定系统函数       打开文件对话框
    [DllImport("Comdlg32.dll", SetLastError = true, ThrowOnUnmappableChar = true, CharSet = CharSet.Auto)]
    public static extern bool GetOpenFileName([In, Out] OpenFileName ofn);
    public static bool GetOFN([In, Out] OpenFileName ofn)
    {
        return GetOpenFileName(ofn);
    }
    //链接指定系统函数        另存为对话框
    [DllImport("Comdlg32.dll", SetLastError = true, ThrowOnUnmappableChar = true, CharSet = CharSet.Auto)]
    public static extern bool GetSaveFileName([In, Out] OpenFileName ofn);
    public static bool GetSFN([In, Out] OpenFileName ofn)
    {
        return GetSaveFileName(ofn);
    }
}

导入

导入参考图
mesh文件,开发记录,开发语言,unity,c#,unity3d

  /// <summary>
    /// 选择导入路径
    /// </summary>
    public void InputFile()
    {      
        file = "";
        OpenFileName openFileName = new OpenFileName();
        openFileName.structSize = Marshal.SizeOf(openFileName);      
        openFileName.filter = "模型文件(*.obj)\0*.obj";
        openFileName.file = new string(new char[256]);
        openFileName.maxFile = openFileName.file.Length;
        openFileName.fileTitle = new string(new char[64]);
        openFileName.maxFileTitle = openFileName.fileTitle.Length;
        openFileName.initialDir = Application.streamingAssetsPath.Replace('/', '\\');//默认路径
        openFileName.title = "导入";
        openFileName.flags = 0x00080000 | 0x00001000 | 0x00000800 | 0x00000008;
        if (LocalDialog.GetOpenFileName(openFileName))
        {
            file = openFileName.file;
        }

    }
  

导出

设置格式 \0*.obj\0 和 \0*.stl\0,这种形式是分开显示格式,下图所示; \0*.obj *.stl\0 这种显示在一起,导入参考图所示。
mesh文件,开发记录,开发语言,unity,c#,unity3d

  /// <summary>
    /// 选择导出路径
    /// </summary>
    void OutputFile()
    {
        if (Manager3.instance.cylinder==null )
        {
            textTips.text = "未加载工件!";
            return;
        }
     
        file = "";       
        OpenFileName openFileName = new OpenFileName();
        openFileName.structSize = Marshal.SizeOf(openFileName);
        openFileName.filter = "模型文件(*.obj)\0*.obj\0模型文件(*.stl)\0*.stl\0";
        openFileName.file = new string(new char[256]);
        openFileName.maxFile = openFileName.file.Length;
        openFileName.fileTitle = new string(new char[64]);
        openFileName.maxFileTitle = openFileName.fileTitle.Length;
        openFileName.initialDir = Application.streamingAssetsPath.Replace('/', '\\');//默认路径
        openFileName.title = "导出";
        openFileName.flags = 0x00080000 | 0x00001000 | 0x00000800 | 0x00000008;
        openFileName.defExt = ".obj";
     
        if (LocalDialog.GetSaveFileName(openFileName))
        {
            file = openFileName.file;
        }
    }

注意事项

1.不建议在编辑器中频繁调用win。可能引起Library错误,导致资源全部丢失,需要删除Library,重新加载场景。
2. openFileName.defExt = “.obj”; 这个重点,选择格式后,自动在输入框中追加后缀。不设置defExt 值时,需要自己追加。
mesh文件,开发记录,开发语言,unity,c#,unity3d文章来源地址https://www.toymoban.com/news/detail-648992.html

到了这里,关于mesh导出OBJ、STL格式和win窗口调用的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • obj文件格式与.mtl文件格式

    1. OBJ 是一种 3D模型文件,因此 不包含动画、材质特性、贴图路径、动力学、粒子 等信息。但是可以读取 .mtl 文件 来获得材质信息。 2.OBJ 文件使用【根据数据类型排列,每个有一段简短描述】     顶点数据 (Vertex data) : v  几何体顶点 (Geometric vertices) vt 贴图坐

    2024年02月05日
    浏览(73)
  • Unity场景素材导出为 OBJ文件的方法

    一、Unity场景素材导出为 FBX文件的方法:http://t.csdn.cn/Xyjxe 二、Unity场景素材导出为 OBJ文件的方法:http://t.csdn.cn/08RY3 三、Unity地形导出为 OBJ文件的方法 (大家可以打开我的博客主页进行查看此系列其它文章) 目录 系列文章目录 前言 一、Unity场景素材导出OBJ文件 安装插件

    2024年02月10日
    浏览(56)
  • 3D文件格式之OBJ介绍

          在 instant-ngp 中使用NeRF时,保存的mesh可指定为obj,这里对obj文件格式进行说明。       OBJ文件(.obj)包含有关3D对象的几何体的信息 。OBJ文件可以支持无限的颜色(unlimited colors),一个文件可以定义多个对象。       OBJ文件中的对象由多边形面(它们本身由顶点或点定义)和

    2024年02月01日
    浏览(36)
  • Wavefront .OBJ文件格式解读【3D】

    OBJ(或 .OBJ)是一种几何定义文件格式,最初由 Wavefront Technologies 为其高级可视化器动画包开发。 该文件格式是开放的,已被其他 3D 图形应用程序供应商采用。 OBJ 文件格式是一种简单的数据格式,仅表示 3D 几何体,即每个顶点的位置、顶点UV坐标、顶点法线以及使每个多边

    2024年02月12日
    浏览(30)
  • 3d max的obj文件格式说明

    OBJ 文件格式是一种常见的 3D 模型文件格式,它包含了模型的几何形状、材质、纹理等信息。下面是 OBJ 文件格式的一些基本信息: OBJ 文件由一系列文本行组成,每行以一个开头,后面跟着一些参数。OBJ 文件中最常见的有以下几个: v :定义一个顶点,后

    2024年03月09日
    浏览(36)
  • 读取3D文件mesh格式工具

    最近要做一个3d仪表,所以了解了一下3d相关方面的知识。这里暂时不做一一赘述,只记录下当前的需求。 需求:         由于****.mesh文件比较多,qt转换后的名字大多都能顾名思义,但是为了更加准确的找到某个部件,于是需要一个工具可以打开并查看****.mesh文件。自己

    2024年02月12日
    浏览(44)
  • 3D开发程序员,如何在程序中将GLB格式转OBJ

    Aspose.3D 是一个功能丰富的游戏软件和计算机辅助设计(CAD)的API,可以在不依赖任何3D建模和渲染软件的情况下操作文档。API支持Discreet3DS, WavefrontOBJ, FBX (ASCII, Binary), STL (ASCII, Binary), Universal3D, Collada, glTF, GLB, PLY, DirectX, Google Draco文件格式等等。开发人员可以轻松地创建,读取

    2024年01月24日
    浏览(41)
  • [visionOS] [Apple Vision Pro] 3D模型文件格式转换:obj转usdz

    1,先要安装好Python3.7 【必须是Python3.7.x版本】 到Python官方去下载macOS版的Python3.7.x安装包 Python Releases for macOS | Python.org 要注意找一下,有些 3.7.x版本没有macOS安装包, 这里直接给出其中两个可以下载的 Python 3.7.8rc1 - June 17, 2020 Download macOS 64-bit installer Python 3.7.9 - Aug. 17, 2020

    2024年02月16日
    浏览(107)
  • 如何使用 ThreeJs 以 glTF、FBX 和 OBJ 文件格式加载 3D 模型,使用 ThreeJS 加载和显示带有纹理的 3D 模型

    在本文中,我展示了如何使用 ThreeJS 在 Web 视图中加载 3D 模型。Three.js 是一个跨浏览器的 JavaScript 库和应用程序编程接口,用于使用 WebGL 在 Web 浏览器中创建和显示动画 3D 计算机图形。加载不完整的原因有很多,例如纹理和材质渲染不正确。 创建场景 渲染场景 动画立方体

    2023年04月08日
    浏览(50)
  • STL文件格式详解【3D】

    STL(StereoLithography:立体光刻)文件是 3 维表面几何形状的三角形表示。 表面被逻辑地细分或分解为一系列小三角形(面)。 每个面由垂直方向和代表三角形顶点(角)的三个点来描述。 切片算法使用这些数据来确定制造商要构建的 3 维形状的横截面。 本文描述了 STL 文件

    2024年02月13日
    浏览(41)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包