天天看點

WPF下的3d模型導出,從MeshGeometry3D 導出到 obj 檔案

MeshGeometry3D時WPF中的一種3d顯示類,之前有人發帖解決了從3dmax檔案自動生成MeshGeometry3D的方法(http://www.cnblogs.com/enjoyeclipse/archive/2012/03/21/2410439.html)。

這裡反其道而行釋出一種将MeshGeometry3D模型導出到obj檔案格式可以使用3dmax打開檢視。

内容如下:

using System;
 using System.Collections.Generic;
 using System.Linq;
 using System.Text;
 using System.Windows.Media.Imaging;
 using System.IO;
 using System.Windows.Media.Media3D;
 using System.Windows;
 
 namespace ZUI.Tools
 {
     public class ObjWriter
     {
         MeshGeometry3D _model;
         BitmapSource _texture;
 
         const string SPLITER = "#==================================================================================================";
         const string STR_BETWEEN_BLOCKS = "\r\n\r\n\r\n\r\n";
 
         public ObjWriter(MeshGeometry3D modle, BitmapSource texture)
         {
             _model = modle;
             _texture = texture;
         }
 
         public void OutPut(string fileName,string fileSafeName)
         {
             CreatObj(fileName, fileSafeName);
             CreatMtl(fileName, fileSafeName);
             CreatReadMe(fileName, fileSafeName);
             CreatTexture(fileName);
         }
         public void CreatReadMe(string fileName, string fileSafeName)
         {
             FileStream fileStream = new FileStream(fileName + "Read Me.txt", FileMode.Create, FileAccess.ReadWrite);
             StreamWriter streamWriter = new StreamWriter(fileStream);
 
             streamWriter.WriteLine(SPLITER);
             streamWriter.WriteLine("#");
             streamWriter.WriteLine("#  Those files listed below is auto generated. Please DO NOT edit them !  ");
             streamWriter.WriteLine("#  You can run the first file in meshlab or 3dmax . But you MUST have all those THREE files !");
             streamWriter.WriteLine("#  If you have more question please send e-mail to \"[email protected]\".");
             streamWriter.WriteLine("#");
             streamWriter.WriteLine("#  1. " + fileSafeName);
             streamWriter.WriteLine("#  2. " + fileSafeName+".bmp");
             streamWriter.WriteLine("#  3. " + fileSafeName+".mtl");
             streamWriter.WriteLine("#");
             streamWriter.WriteLine("#  Thank you ! And have a nice day !");
             streamWriter.WriteLine("#  Generated Time : " + DateTime.Now.ToString());
             streamWriter.WriteLine(SPLITER);
 
             streamWriter.Flush();
             streamWriter.Close();
             fileStream.Close();
         }
 
         private void CreatTexture(string fileName)
         {
             FileStream fileStream = new FileStream(fileName + ".bmp", FileMode.Create, FileAccess.ReadWrite);
 
             BmpBitmapEncoder encoder = new BmpBitmapEncoder();
             encoder.Frames.Add(BitmapFrame.Create(_texture)) ;
             encoder.Save(fileStream);
 
             fileStream.Close();
         }
 
         private void CreatMtl(string fileName, string fileSafeName)
         {
             FileStream fileStream = new FileStream(fileName + ".mtl", FileMode.Create, FileAccess.ReadWrite);
             StreamWriter streamWriter = new StreamWriter(fileStream);
 
             streamWriter.WriteLine(SPLITER);
             streamWriter.WriteLine("#");
             streamWriter.WriteLine("# Warming        : This file is auto generated . Please DO NOT edit it ! ");
             streamWriter.WriteLine("#");
             streamWriter.WriteLine("# Generated Time : " + DateTime.Now.ToString());
             streamWriter.WriteLine("#");
             streamWriter.WriteLine("# Description    :You can open this file in meshlab or 3dmax .");
             streamWriter.WriteLine("#                 If you have more question please send e-mail to \"[email protected]\".");
             streamWriter.WriteLine("#                 This file MUST work with other two files named:\"" + fileSafeName + "\" and \"" + fileSafeName + ".bmp\".");
             streamWriter.WriteLine("#");
             streamWriter.WriteLine(SPLITER);
             streamWriter.WriteLine(STR_BETWEEN_BLOCKS);
 
             streamWriter.WriteLine("newmtl mt1");
             streamWriter.WriteLine("Ka 0.0000 0.0000 0.0000");
             streamWriter.WriteLine("Kd 0.0000 0.0000 0.0000");
             streamWriter.WriteLine("Ks 0.0000 0.0000 0.0000");
             streamWriter.WriteLine("Ke 0.9725 0.9725 0.9725");
 
             streamWriter.WriteLine("map_Ka " + fileSafeName + ".bmp");
             streamWriter.WriteLine("map_Kd " + fileSafeName + ".bmp");
 
 
             streamWriter.Flush();
             streamWriter.Close();
             fileStream.Close();
         }
 
         private void CreatObj(string fileName, string fileSafeName)
         {
             FileStream fileStream = new FileStream(fileName, FileMode.Create, FileAccess.ReadWrite);
             StreamWriter streamWriter = new StreamWriter(fileStream);
 
             streamWriter.WriteLine(GetHeadString(fileSafeName));
             streamWriter.WriteLine(STR_BETWEEN_BLOCKS);
 
             streamWriter.WriteLine(GetMatralString(fileSafeName));
             streamWriter.WriteLine(STR_BETWEEN_BLOCKS);
 
             streamWriter.Write(GetVerticesString());
             streamWriter.WriteLine(STR_BETWEEN_BLOCKS);
 
             streamWriter.Write(GetTexturePointString());
             streamWriter.WriteLine(STR_BETWEEN_BLOCKS);
 
             streamWriter.Write(GetFaceString());
 
             streamWriter.Flush();
             streamWriter.Close();
             fileStream.Close();
         }
 
         private string GetHeadString(string fileSafeName)
         {
             StringBuilder result = new StringBuilder();
 
             result.AppendLine(SPLITER);
             result.AppendLine("#");
             result.AppendLine("# Warming        : This file is auto generated . Please DO NOT edit it ! ");
             result.AppendLine("#");
             result.AppendLine("# Generated Time : "+DateTime.Now.ToString());
             result.AppendLine("#");
             result.AppendLine("# Description    :You can open this file in meshlab or 3dmax .");
             result.AppendLine("#                 If you have more question please send e-mail to \"[email protected]\".");
             result.AppendLine("#                 This file MUST work with other two files named:\"" + fileSafeName + ".mtl\" and \""+fileSafeName+".bmp\".");
             result.AppendLine("#");
             result.AppendLine(SPLITER);
 
             return result.ToString();
         }
 
         private string GetMatralString(string fileSafeName)
         {
             StringBuilder result = new StringBuilder();
 
             result.AppendLine(SPLITER + "\r\n");
             result.AppendLine("#  Matral : 1  \r\n");
             result.AppendLine("mtllib " + fileSafeName + ".mtl");
             result.AppendLine("\r\n#  Matral End \r\n");
             result.AppendLine(SPLITER );
 
             return result.ToString();
         }
 
         private string GetVerticesString()
         {
             StringBuilder result = new StringBuilder();
 
             result.AppendLine(SPLITER+"\r\n");
             result.AppendLine("#  Vertices: "+ _model.Positions.Count + "\r\n");
 
             foreach (Point3D p in _model.Positions)
                result.AppendLine("v " + p.X + " " + p.Y + " " + p.Z);
 
             result.AppendLine("\r\n#  Vertices End");
             result.AppendLine("\r\n" + SPLITER);
 
             return result.ToString();
         }
 
         private string GetTexturePointString()
         {
             StringBuilder result = new StringBuilder();
 
             result.AppendLine(SPLITER + "\r\n");
             result.AppendLine("#  Texture Coordinates: " + _model.TextureCoordinates.Count + "\r\n");
 
             foreach(Point p in _model.TextureCoordinates)
                  result.AppendLine("vt " + p.X  + " " + p.Y + " 0");
 
 
             result.AppendLine("\r\n#  Texture Coordinates End");
             result.AppendLine("\r\n" + SPLITER);
 
             return result.ToString();
         }
 
         private string GetFaceString()
         {
             StringBuilder result = new StringBuilder();
 
             result.AppendLine(SPLITER + "\r\n");
             result.AppendLine("#  Faces: " + _model.TriangleIndices.Count/3 + "\r\n");
             result.AppendLine("usemtl mt1" + "\r\n");
 
             for (int i = 0; i < _model.TriangleIndices.Count - 1; i+=3)
             {
 
                 result.Append("f ");
 
                 int p1 = _model.TriangleIndices[i] + 1;
                 int p2 = _model.TriangleIndices[i + 1] + 1;
                 int p3 = _model.TriangleIndices[i + 2] + 1;
 
                 result.Append(p1 + "/" + p1 + " ");
                 result.Append(p2 + "/" + p2 + " ");
                 result.Append(p3 + "/" + p3 + " ");
 
                 result.AppendLine();
              }
 
             result.AppendLine("\r\n#  Faces End");
             result.AppendLine("\r\n" + SPLITER);
 
             return result.ToString();
         }
     }
 }
           

調用方法如下:添加一個按鈕

private void ObjOutPut_Click(object sender, RoutedEventArgs e)
         {
             try
             {
                 if (Modle == null || Modle.Geometry == null)
                 {
                     MessageBox.Show("模型不能為空");
                     return;
                 }
                 SaveFileDialog dialog = new SaveFileDialog();
                 dialog.Filter = "模型(*.obj)|*.obj";
                 dialog.FileName = Title;
                 dialog.Title = "儲存模型";
 
                 double r = sliderrate.Value;
                 if (dialog.ShowDialog() == true)
                 {
                     ObjWriter ow = new ObjWriter(Modle.Geometry as MeshGeometry3D, _texture);
                     ow.OutPut(dialog.FileName,dialog.SafeFileName);
                     MessageBox.Show("Output Success !");
                 }
             }
             catch (Exception ex)
             {
                 MessageBox.Show(ex.Message);
             }
         }
           

已驗證過,簡單易用

轉自:http://www.cnblogs.com/GhostZCH/archive/2012/06/14/2549711.html

繼續閱讀