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 \"[email protected]\".");

 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 \"[email protected]\".");

 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 \"[email protected]\".");

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个文件

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

全名如下:

#  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文件结构

 

你可能感兴趣的:(WPF)