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