WPF下的3d模型导出,从MeshGeometry3D 导出到 obj 文件

MeshGeometry3D时WPF中的一种3d显示类,之前有人发帖解决了从3dmax文件自动生成MeshGeometry3D的方法(http://www.cnblogs.com/enjoyeclipse/archive/2012/03/21/2410439.html)。

这里反其道而行发布一种将MeshGeometry3D模型导出到obj文件格式可以使用3dmax打开查看。

内容如下:

  1 using System;
  2 using System.Collections.Generic;
  3 using System.Linq;
  4 using System.Text;
  5 using System.Windows.Media.Imaging;
  6 using System.IO;
  7 using System.Windows.Media.Media3D;
  8 using System.Windows;
  9 
 10 namespace ZUI.Tools
 11 {
 12     public class ObjWriter
 13     {
 14         MeshGeometry3D _model;
 15         BitmapSource _texture;
 16 
 17         const string SPLITER = "#==================================================================================================";
 18         const string STR_BETWEEN_BLOCKS = "\r\n\r\n\r\n\r\n";
 19 
 20         public ObjWriter(MeshGeometry3D modle, BitmapSource texture)
 21         {
 22             _model = modle;
 23             _texture = texture;
 24         }
 25 
 26         public void OutPut(string fileName,string fileSafeName)
 27         {
 28             CreatObj(fileName, fileSafeName);
 29             CreatMtl(fileName, fileSafeName);
 30             CreatReadMe(fileName, fileSafeName);
 31             CreatTexture(fileName);
 32         }
 33         public void CreatReadMe(string fileName, string fileSafeName)
 34         {
 35             FileStream fileStream = new FileStream(fileName + "Read Me.txt", FileMode.Create, FileAccess.ReadWrite);
 36             StreamWriter streamWriter = new StreamWriter(fileStream);
 37 
 38             streamWriter.WriteLine(SPLITER);
 39             streamWriter.WriteLine("#");
 40             streamWriter.WriteLine("#  Those files listed below is auto generated. Please DO NOT edit them !  ");
 41             streamWriter.WriteLine("#  You can run the first file in meshlab or 3dmax . But you MUST have all those THREE files !");
 42             streamWriter.WriteLine("#  If you have more question please send e-mail to \"zhao_chenhui_scu@163.com\".");
 43             streamWriter.WriteLine("#");
 44             streamWriter.WriteLine("#  1. " + fileSafeName);
 45             streamWriter.WriteLine("#  2. " + fileSafeName+".bmp");
 46             streamWriter.WriteLine("#  3. " + fileSafeName+".mtl");
 47             streamWriter.WriteLine("#");
 48             streamWriter.WriteLine("#  Thank you ! And have a nice day !");
 49             streamWriter.WriteLine("#  Generated Time : " + DateTime.Now.ToString());
 50             streamWriter.WriteLine(SPLITER);
 51 
 52             streamWriter.Flush();
 53             streamWriter.Close();
 54             fileStream.Close();
 55         }
 56 
 57         private void CreatTexture(string fileName)
 58         {
 59             FileStream fileStream = new FileStream(fileName + ".bmp", FileMode.Create, FileAccess.ReadWrite);
 60 
 61             BmpBitmapEncoder encoder = new BmpBitmapEncoder();
 62             encoder.Frames.Add(BitmapFrame.Create(_texture)) ;
 63             encoder.Save(fileStream);
 64 
 65             fileStream.Close();
 66         }
 67 
 68         private void CreatMtl(string fileName, string fileSafeName)
 69         {
 70             FileStream fileStream = new FileStream(fileName + ".mtl", FileMode.Create, FileAccess.ReadWrite);
 71             StreamWriter streamWriter = new StreamWriter(fileStream);
 72 
 73             streamWriter.WriteLine(SPLITER);
 74             streamWriter.WriteLine("#");
 75             streamWriter.WriteLine("# Warming        : This file is auto generated . Please DO NOT edit it ! ");
 76             streamWriter.WriteLine("#");
 77             streamWriter.WriteLine("# Generated Time : " + DateTime.Now.ToString());
 78             streamWriter.WriteLine("#");
 79             streamWriter.WriteLine("# Description    :You can open this file in meshlab or 3dmax .");
 80             streamWriter.WriteLine("#                 If you have more question please send e-mail to \"zhao_chenhui_scu@163.com\".");
 81             streamWriter.WriteLine("#                 This file MUST work with other two files named:\"" + fileSafeName + "\" and \"" + fileSafeName + ".bmp\".");
 82             streamWriter.WriteLine("#");
 83             streamWriter.WriteLine(SPLITER);
 84             streamWriter.WriteLine(STR_BETWEEN_BLOCKS);
 85 
 86             streamWriter.WriteLine("newmtl mt1");
 87             streamWriter.WriteLine("Ka 0.0000 0.0000 0.0000");
 88             streamWriter.WriteLine("Kd 0.0000 0.0000 0.0000");
 89             streamWriter.WriteLine("Ks 0.0000 0.0000 0.0000");
 90             streamWriter.WriteLine("Ke 0.9725 0.9725 0.9725");
 91 
 92             streamWriter.WriteLine("map_Ka " + fileSafeName + ".bmp");
 93             streamWriter.WriteLine("map_Kd " + fileSafeName + ".bmp");
 94 
 95 
 96             streamWriter.Flush();
 97             streamWriter.Close();
 98             fileStream.Close();
 99         }
100 
101         private void CreatObj(string fileName, string fileSafeName)
102         {
103             FileStream fileStream = new FileStream(fileName, FileMode.Create, FileAccess.ReadWrite);
104             StreamWriter streamWriter = new StreamWriter(fileStream);
105 
106             streamWriter.WriteLine(GetHeadString(fileSafeName));
107             streamWriter.WriteLine(STR_BETWEEN_BLOCKS);
108 
109             streamWriter.WriteLine(GetMatralString(fileSafeName));
110             streamWriter.WriteLine(STR_BETWEEN_BLOCKS);
111 
112             streamWriter.Write(GetVerticesString());
113             streamWriter.WriteLine(STR_BETWEEN_BLOCKS);
114 
115             streamWriter.Write(GetTexturePointString());
116             streamWriter.WriteLine(STR_BETWEEN_BLOCKS);
117 
118             streamWriter.Write(GetFaceString());
119 
120             streamWriter.Flush();
121             streamWriter.Close();
122             fileStream.Close();
123         }
124 
125         private string GetHeadString(string fileSafeName)
126         {
127             StringBuilder result = new StringBuilder();
128 
129             result.AppendLine(SPLITER);
130             result.AppendLine("#");
131             result.AppendLine("# Warming        : This file is auto generated . Please DO NOT edit it ! ");
132             result.AppendLine("#");
133             result.AppendLine("# Generated Time : "+DateTime.Now.ToString());
134             result.AppendLine("#");
135             result.AppendLine("# Description    :You can open this file in meshlab or 3dmax .");
136             result.AppendLine("#                 If you have more question please send e-mail to \"zhao_chenhui_scu@163.com\".");
137             result.AppendLine("#                 This file MUST work with other two files named:\"" + fileSafeName + ".mtl\" and \""+fileSafeName+".bmp\".");
138             result.AppendLine("#");
139             result.AppendLine(SPLITER);
140 
141             return result.ToString();
142         }
143 
144         private string GetMatralString(string fileSafeName)
145         {
146             StringBuilder result = new StringBuilder();
147 
148             result.AppendLine(SPLITER + "\r\n");
149             result.AppendLine("#  Matral : 1  \r\n");
150             result.AppendLine("mtllib " + fileSafeName + ".mtl");
151             result.AppendLine("\r\n#  Matral End \r\n");
152             result.AppendLine(SPLITER );
153 
154             return result.ToString();
155         }
156 
157         private string GetVerticesString()
158         {
159             StringBuilder result = new StringBuilder();
160 
161             result.AppendLine(SPLITER+"\r\n");
162             result.AppendLine("#  Vertices: "+ _model.Positions.Count + "\r\n");
163 
164             foreach (Point3D p in _model.Positions)
165                result.AppendLine("v " + p.X + " " + p.Y + " " + p.Z);
166 
167             result.AppendLine("\r\n#  Vertices End");
168             result.AppendLine("\r\n" + SPLITER);
169 
170             return result.ToString();
171         }
172 
173         private string GetTexturePointString()
174         {
175             StringBuilder result = new StringBuilder();
176 
177             result.AppendLine(SPLITER + "\r\n");
178             result.AppendLine("#  Texture Coordinates: " + _model.TextureCoordinates.Count + "\r\n");
179 
180             foreach(Point p in _model.TextureCoordinates)
181                  result.AppendLine("vt " + p.X  + " " + p.Y + " 0");
182 
183 
184             result.AppendLine("\r\n#  Texture Coordinates End");
185             result.AppendLine("\r\n" + SPLITER);
186 
187             return result.ToString();
188         }
189 
190         private string GetFaceString()
191         {
192             StringBuilder result = new StringBuilder();
193 
194             result.AppendLine(SPLITER + "\r\n");
195             result.AppendLine("#  Faces: " + _model.TriangleIndices.Count/3 + "\r\n");
196             result.AppendLine("usemtl mt1" + "\r\n");
197 
198             for (int i = 0; i < _model.TriangleIndices.Count - 1; i+=3)
199             {
200 
201                 result.Append("f ");
202 
203                 int p1 = _model.TriangleIndices[i] + 1;
204                 int p2 = _model.TriangleIndices[i + 1] + 1;
205                 int p3 = _model.TriangleIndices[i + 2] + 1;
206 
207                 result.Append(p1 + "/" + p1 + " ");
208                 result.Append(p2 + "/" + p2 + " ");
209                 result.Append(p3 + "/" + p3 + " ");
210 
211                 result.AppendLine();
212              }
213 
214             result.AppendLine("\r\n#  Faces End");
215             result.AppendLine("\r\n" + SPLITER);
216 
217             return result.ToString();
218         }
219     }
220 }

使用方法如下:

 1  private void ObjOutPut_Click(object sender, RoutedEventArgs e)
 2         {
 3             try
 4             {
 5                 if (Modle == null || Modle.Geometry == null)
 6                 {
 7                     MessageBox.Show("模型不能为空");
 8                     return;
 9                 }
10                 SaveFileDialog dialog = new SaveFileDialog();
11                 dialog.Filter = "模型(*.obj)|*.obj";
12                 dialog.FileName = Title;
13                 dialog.Title = "保存模型";
14 
15                 double r = sliderrate.Value;
16                 if (dialog.ShowDialog() == true)
17                 {
18                     ObjWriter ow = new ObjWriter(Modle.Geometry as MeshGeometry3D, _texture);
19                     ow.OutPut(dialog.FileName,dialog.SafeFileName);
20                     MessageBox.Show("Output Success !");
21                 }
22             }
23             catch (Exception ex)
24             {
25                 MessageBox.Show(ex.Message);
26             }
27         }

运行的结果导出4个文件

全名如下:

#  1. box.obj
#  2. box.obj.bmp
#  3. box.obj.mtl

#  4.box.objRead Me.txt

其中前三个是有用的可以用第一个导入3dMAX

 

参考:

http://www.cppblog.com/lovedday/archive/2008/06/13/53153.html obj文件结构

http://hi.baidu.com/ab_xyz/blog/item/efff4fc518a11ba48326acbe.html  mtl文件结构

 

posted @ 2012-06-14 18:45  Ghost_zhao  阅读(2755)  评论(0编辑  收藏  举报