前言

helix.toolkit封装了模型加载的操作,由于按照了标准模型的读取,出现材质或者贴图找不到的情况,容易模型加载异常。因此解决办法是,如果相关资源没找到的话,默认赋上默认材质来解决。

附上本文demo

(10条消息) helix.toolkit封装了模型加载的操作,由于按照了标准模型的读取,出现材质或者贴图找不到的情况,容易模型加载异常。因此解-C#文档类资源-CSDN文库

详细内容

helix中封装了对模型类型文件的读取操作,如下

 private async Task<Model3DGroup> LoadAsync(string model3DPath, bool freeze){return await Task.Factory.StartNew(() =>{var mi = new ModelImporter2.ModelImporter();if (freeze){// Alt 1. - freeze the model return mi.Load(model3DPath, null, true);}// Alt. 2 - create the model on the UI dispatcherreturn mi.Load(model3DPath, this.dispatcher);});}

f12进去看,能够看到ObjReader层级,问题就出来了ObjReader默认加载模型自带的贴图或者材质,如果找不到,模型就加载不出来,因此解决办法自然是“让代码正常运行”先。给模型加载默认的材质。

 /// <summary>/// Loads a model from the specified path./// </summary>/// <param name="path">The path.</param>/// <param name="dispatcher">The dispatcher used to create the model.</param>/// <param name="freeze">Freeze the model if set to <c>true</c>.</param>/// <returns>A model.</returns>/// <exception cref="System.InvalidOperationException">File format not supported.</exception>public Model3DGroup Load(string path, Dispatcher dispatcher = null, bool freeze = false){if (path == null){return null;}if (dispatcher == null){dispatcher = Dispatcher.CurrentDispatcher;}Model3DGroup model;var ext = Path.GetExtension(path);if (ext != null){ext = ext.ToLower();}switch (ext){case ".3ds":{var r = new StudioReader(dispatcher) { DefaultMaterial = this.DefaultMaterial, Freeze = freeze };model = r.Read(path);break;}case ".lwo":{var r = new LwoReader(dispatcher) { DefaultMaterial = this.DefaultMaterial, Freeze = freeze };model = r.Read(path);break;}case ".obj":{var r = new ObjReader2(dispatcher) { DefaultMaterial = this.DefaultMaterial, Freeze = freeze };model = r.Read(path);break;}case ".objz":{var r = new ObjReader(dispatcher) { DefaultMaterial = this.DefaultMaterial, Freeze = freeze };model = r.ReadZ(path);break;}case ".stl":{var r = new StLReader(dispatcher) { DefaultMaterial = this.DefaultMaterial, Freeze = freeze };model = r.Read(path);break;}case ".off":{var r = new OffReader(dispatcher) { DefaultMaterial = this.DefaultMaterial, Freeze = freeze };model = r.Read(path);break;}case ".ply":{var r = new PlyReader(dispatcher) { DefaultMaterial = this.DefaultMaterial, Freeze = freeze };model = r.Read(path);break;}default:throw new InvalidOperationException("File format not supported.");}//if (!freeze)//{//    dispatcher.Invoke(new Action(() => model.SetName(Path.GetFileName(path))));//}return model;}

修改后的objreader实现如下:

public class ObjReader2 : ModelReader{private static readonly char[] Delimiters = new char[] { ' ' };/// <summary>/// The smoothing group maps./// </summary>/// <remarks>/// The outer dictionary maps from a smoothing group number to a dictionary./// The inner dictionary maps from an obj file (vertex, texture coordinates, normal) index to a vertex index in the current group./// </remarks>private readonly Dictionary<long, Dictionary<Tuple<int, int, int>, int>> smoothingGroupMaps;/// <summary>/// The current smoothing group./// </summary>private long currentSmoothingGroup;/// <summary>/// The line number of the line being parsed./// </summary>private int currentLineNo;/// <summary>/// Initializes a new instance of the <see cref="ObjReader" /> class./// </summary>/// <param name="dispatcher">The dispatcher.</param>public ObjReader2(Dispatcher dispatcher = null): base(dispatcher){this.IgnoreErrors = false;this.SwitchYZ = false;this.IsSmoothingDefault = true;this.SkipTransparencyValues = true;this.Points = new List<Point3D>();this.TextureCoordinates = new List<Point>();this.Normals = new List<Vector3D>();this.Groups = new List<Group>();this.Materials = new Dictionary<string, MaterialDefinition>();this.smoothingGroupMaps = new Dictionary<long, Dictionary<Tuple<int, int, int>, int>>();// File format specifications// http://en.wikipedia.org/wiki/Obj// http://en.wikipedia.org/wiki/Material_Template_Library// http://www.martinreddy.net/gfx/3d/OBJ.spec// http://www.eg-models.de/formats/Format_Obj.html}/// <summary>/// Gets or sets a value indicating whether to ignore errors./// </summary>/// <value><c>true</c> if errors should be ignored; <c>false</c> if errors should throw an exception.</value>/// <remarks>/// The default value is on (true)./// </remarks>public bool IgnoreErrors { get; set; }/// <summary>/// Gets or sets a value indicating whether to switch Y and Z coordinates./// </summary>public bool SwitchYZ { get; set; }/// <summary>/// Gets or sets a value indicating whether to skip transparency values in the material files./// </summary>/// <value>/// <c>true</c> if transparency values should be skipped; otherwise, <c>false</c>./// </value>/// <remarks>/// This option is added to allow disabling the <code>Tr</code> values in files where it has been defined incorrectly./// The transparency values (<code>Tr</code>) are interpreted as 0 = transparent, 1 = opaque./// The dissolve values (<code>d</code>) are interpreted as 0 = transparent, 1 = opaque./// </remarks>public bool SkipTransparencyValues { get; set; }/// <summary>/// Sets a value indicating whether smoothing is default./// </summary>/// <remarks>/// The default value is smoothing=on (true)./// </remarks>public bool IsSmoothingDefault{set{this.currentSmoothingGroup = value ? 1 : 0;}}/// <summary>/// Gets the groups of the file./// </summary>/// <value>The groups.</value>public IList<Group> Groups { get; private set; }/// <summary>/// Gets the materials in the imported material files./// </summary>/// <value>The materials.</value>public Dictionary<string, MaterialDefinition> Materials { get; private set; }/// <summary>/// Gets or sets the current material./// </summary>private Material CurrentMaterial { get; set; }/// <summary>/// Gets the current group./// </summary>private Group CurrentGroup{get{if (this.Groups.Count == 0){this.AddGroup("default");}return this.Groups[this.Groups.Count - 1];}}/// <summary>/// Gets or sets the normal vectors./// </summary>private IList<Vector3D> Normals { get; set; }/// <summary>/// Gets or sets the points./// </summary>private IList<Point3D> Points { get; set; }/// <summary>/// Gets or sets the stream reader./// </summary>private StreamReader Reader { get; set; }/// <summary>/// Gets or sets the texture coordinates./// </summary>private IList<Point> TextureCoordinates { get; set; }/// <summary>/// Reads the model and any associated materials from streams/// </summary>/// <param name="objStream">A model stream from the obj file</param>/// <param name="mtlStreams">Array of Material streams referenced in the obj file</param>/// <returns></returns>public Model3DGroup Read(Stream objStream, Stream[] mtlStreams){foreach (var mtlStream in mtlStreams){using (var mtlStreamReader = new StreamReader(mtlStream)){ReadMaterial(mtlStreamReader);}}return Read(objStream);}/// <summary>/// Reads the model from the specified path./// </summary>/// <param name="path">The path.</param>/// <returns>The model.</returns>public override Model3DGroup Read(string path){this.TexturePath = Path.GetDirectoryName(path);using (var s = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read)){return this.Read(s);}}/// <summary>/// Reads the model from the specified stream./// </summary>/// <param name="s">The stream.</param>/// <returns>The model.</returns>public override Model3DGroup Read(Stream s){using (this.Reader = new StreamReader(s)){this.currentLineNo = 0;while (!this.Reader.EndOfStream){this.currentLineNo++;var line = this.Reader.ReadLine();if (line == null){break;}line = line.Trim();while (line.EndsWith("\\")){var nextLine = this.Reader.ReadLine();while (nextLine.Length == 0){nextLine = this.Reader.ReadLine();}line = line.TrimEnd('\\') + nextLine;}if (line.StartsWith("#") || line.Length == 0){continue;}string keyword, values;SplitLine(line, out keyword, out values);switch (keyword.ToLower()){// Vertex datacase "v": // geometric verticesthis.AddVertex(values);break;case "vt": // texture verticesthis.AddTexCoord(values);break;case "vn": // vertex normalsthis.AddNormal(values);break;case "vp": // parameter space verticescase "cstype": // rational or non-rational forms of curve or surface type: basis matrix, Bezier, B-spline, Cardinal, Taylorcase "degree": // degreecase "bmat": // basis matrixcase "step": // step size// not supportedbreak;// Elementscase "f": // facethis.AddFace(values);break;case "p": // pointcase "l": // linecase "curv": // curvecase "curv2": // 2D curvecase "surf": // surface// not supportedbreak;// Free-form curve/surface body statementscase "parm": // parameter namecase "trim": // outer trimming loop (trim)case "hole": // inner trimming loop (hole)case "scrv": // special curve (scrv)case "sp":  // special point (sp)case "end": // end statement (end)// not supportedbreak;// Connectivity between free-form surfacescase "con": // connect// not supportedbreak;// Groupingcase "g": // group namethis.AddGroup(values);break;case "s": // smoothing groupthis.SetSmoothingGroup(values);break;case "mg": // merging groupbreak;case "o": // object name// not supportedbreak;// Display/render attributescase "mtllib": // material librarythis.LoadMaterialLib(values);break;case "usemtl": // material namethis.EnsureNewMesh();this.SetMaterial(values);break;case "usemap": // texture map namethis.EnsureNewMesh();break;case "bevel": // bevel interpolationcase "c_interp": // color interpolationcase "d_interp": // dissolve interpolationcase "lod": // level of detailcase "shadow_obj": // shadow castingcase "trace_obj": // ray tracingcase "ctech": // curve approximation techniquecase "stech": // surface approximation technique// not supportedbreak;}}}return this.BuildModel();}/// <summary>/// Reads a GZipStream compressed OBJ file./// </summary>/// <param name="path">The path.</param>/// <returns>A Model3D object containing the model.</returns>/// <remarks>This is a file format used by Helix Toolkit only./// Use the GZipHelper class to compress an .obj file.</remarks>public Model3DGroup ReadZ(string path){this.TexturePath = Path.GetDirectoryName(path);using (var s = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read)){var deflateStream = new GZipStream(s, CompressionMode.Decompress, true);return this.Read(deflateStream);}}/// <summary>/// Parses a color string./// </summary>/// <param name="values">/// The input./// </param>/// <returns>/// The parsed color./// </returns>private static Color ColorParse(string values){var fields = Split(values);return Color.FromRgb((byte)(fields[0] * 255), (byte)(fields[1] * 255), (byte)(fields[2] * 255));}/// <summary>/// Parse a string containing a double value./// </summary>/// <param name="input">/// The input string./// </param>/// <returns>/// The value./// </returns>private static double DoubleParse(string input){return double.Parse(input, CultureInfo.InvariantCulture);}/// <summary>/// Splits the specified string using whitespace(input) as separators./// </summary>/// <param name="input">/// The input string./// </param>/// <returns>/// List of input./// </returns>private static IList<double> Split(string input){input = input.Trim();var fields = input.Split(Delimiters, System.StringSplitOptions.RemoveEmptyEntries);var result = new double[fields.Length];for (int i = 0; i < fields.Length; i++){result[i] = DoubleParse(fields[i]);}return result;}/// <summary>/// Splits a line in keyword and arguments./// </summary>/// <param name="line">/// The line./// </param>/// <param name="keyword">/// The keyword./// </param>/// <param name="arguments">/// The arguments./// </param>private static void SplitLine(string line, out string keyword, out string arguments){int idx = line.IndexOf(' ');if (idx < 0){keyword = line;arguments = null;return;}keyword = line.Substring(0, idx);arguments = line.Substring(idx + 1);}/// <summary>/// Adds a group with the specified name./// </summary>/// <param name="name">The name.</param>private void AddGroup(string name){this.Groups.Add(new Group(name, this.CurrentMaterial ?? this.DefaultMaterial));this.smoothingGroupMaps.Clear();}/// <summary>/// Ensures that a new mesh is created./// </summary>private void EnsureNewMesh(){if (this.CurrentGroup.MeshBuilder.TriangleIndices.Count != 0){this.CurrentGroup.AddMesh(this.CurrentMaterial ?? this.DefaultMaterial);this.smoothingGroupMaps.Clear();}}/// <summary>/// Sets the smoothing group number./// </summary>/// <param name="values">The group number.</param>private void SetSmoothingGroup(string values){if (values == "off"){this.currentSmoothingGroup = 0;}else{long smoothingGroup;if (long.TryParse(values, out smoothingGroup)){this.currentSmoothingGroup = smoothingGroup;}else{// invalid parameterif (this.IgnoreErrors){return;}throw new FileFormatException(string.Format("Invalid smoothing group ({0}) at line {1}.", values, this.currentLineNo));}}}/// <summary>/// Adds a face./// </summary>/// <param name="values">/// The input values./// </param>/// <remarks>/// Adds a polygonal face. The numbers are indexes into the arrays of vertex positions,/// texture coordinates, and normal vectors respectively. A number may be omitted if,/// for example, texture coordinates are not being defined in the model./// There is no maximum number of vertices that a single polygon may contain./// The .obj file specification says that each face must be flat and convex./// </remarks>private void AddFace(string values){var currentGroup = this.CurrentGroup;var builder = currentGroup.MeshBuilder;var positions = builder.Positions;var textureCoordinates = builder.TextureCoordinates;var normals = builder.Normals;Dictionary<Tuple<int, int, int>, int> smoothingGroupMap = null;// If a smoothing group is defined, get the map from obj-file-index to current-group-vertex-index.if (this.currentSmoothingGroup != 0){if (!this.smoothingGroupMaps.TryGetValue(this.currentSmoothingGroup, out smoothingGroupMap)){smoothingGroupMap = new Dictionary<Tuple<int, int, int>, int>();this.smoothingGroupMaps.Add(this.currentSmoothingGroup, smoothingGroupMap);}}var fields = values.Split(Delimiters, System.StringSplitOptions.RemoveEmptyEntries);var faceIndices = new List<int>();foreach (var field in fields){if (string.IsNullOrEmpty(field)){continue;}var ff = field.Split('/');int vi = int.Parse(ff[0]);int vti = ff.Length > 1 && ff[1].Length > 0 ? int.Parse(ff[1]) : int.MaxValue;int vni = ff.Length > 2 && ff[2].Length > 0 ? int.Parse(ff[2]) : int.MaxValue;// Handle relative indices (negative numbers)if (vi < 0){vi = this.Points.Count + vi + 1;}if (vti < 0){vti = this.TextureCoordinates.Count + vti + 1;}if (vni < 0){vni = this.Normals.Count + vni + 1;}// Check if the indices are validif (vi - 1 >= this.Points.Count){if (this.IgnoreErrors){return;}throw new FileFormatException(string.Format("Invalid vertex index ({0}) on line {1}.", vi, this.currentLineNo));}if (vti == int.MaxValue){// turn off texture coordinates in the builderbuilder.CreateTextureCoordinates = false;}if (vni == int.MaxValue){// turn off normals in the builderbuilder.CreateNormals = false;}// check if the texture coordinate index is validif (builder.CreateTextureCoordinates && vti - 1 >= this.TextureCoordinates.Count){if (this.IgnoreErrors){return;}throw new FileFormatException(string.Format("Invalid texture coordinate index ({0}) on line {1}.", vti, this.currentLineNo));}// check if the normal index is validif (builder.CreateNormals && vni - 1 >= this.Normals.Count){if (this.IgnoreErrors){return;}throw new FileFormatException(string.Format("Invalid normal index ({0}) on line {1}.", vni, this.currentLineNo));}bool addVertex = true;if (smoothingGroupMap != null){var key = Tuple.Create(vi, vti, vni);int vix;if (smoothingGroupMap.TryGetValue(key, out vix)){// use the index of a previously defined vertexaddVertex = false;}else{// add a new vertexvix = positions.Count;smoothingGroupMap.Add(key, vix);}faceIndices.Add(vix);}else{// if smoothing is off, always add a new vertexfaceIndices.Add(positions.Count);}if (addVertex){// add vertexpositions.Add(this.Points[vi - 1]);// add texture coordinate (if enabled)if (builder.CreateTextureCoordinates){textureCoordinates.Add(this.TextureCoordinates[vti - 1]);}// add normal (if enabled)if (builder.CreateNormals){normals.Add(this.Normals[vni - 1]);}}}if (faceIndices.Count <= 4){// add triangles or quadsbuilder.AddPolygon(faceIndices);}else{// add triangles by cutting ears algorithm// this algorithm is quite expensive...builder.AddPolygonByTriangulation(faceIndices);}}/// <summary>/// Adds a normal./// </summary>/// <param name="values">/// The input values./// </param>private void AddNormal(string values){var fields = Split(values);if (SwitchYZ){this.Normals.Add(new Vector3D(fields[0], -fields[2], fields[1]));}else{this.Normals.Add(new Vector3D(fields[0], fields[1], fields[2]));}}/// <summary>/// Adds a texture coordinate./// </summary>/// <param name="values">/// The input values./// </param>private void AddTexCoord(string values){var fields = Split(values);this.TextureCoordinates.Add(new Point(fields[0], 1 - fields[1]));}/// <summary>/// Adds a vertex./// </summary>/// <param name="values">/// The input values./// </param>private void AddVertex(string values){var fields = Split(values);if (SwitchYZ){this.Points.Add(new Point3D(fields[0], -fields[2], fields[1]));}else{this.Points.Add(new Point3D(fields[0], fields[1], fields[2]));}}/// <summary>/// Builds the model./// </summary>/// <returns>A Model3D object.</returns>private Model3DGroup BuildModel(){Model3DGroup modelGroup = null;this.Dispatch(() =>{modelGroup = new Model3DGroup();foreach (var g in this.Groups){foreach (var gm in g.CreateModels()){gm.SetName(g.Name);if (this.Freeze){gm.Freeze();}modelGroup.Children.Add(gm);}}if (this.Freeze){modelGroup.Freeze();}});return modelGroup;}/// <summary>/// Gets the material with the specified name./// </summary>/// <param name="materialName">/// The material name./// </param>/// <returns>/// The material./// </returns>private Material GetMaterial(string materialName){MaterialDefinition mat;if (!string.IsNullOrEmpty(materialName) && this.Materials.TryGetValue(materialName, out mat)){Material m = null;this.Dispatch(() =>{m = mat.GetMaterial(this.TexturePath);});return m;}return this.DefaultMaterial;}/// <summary>/// Loads a material library./// </summary>/// <param name="mtlFile">/// The material file name./// </param>private void LoadMaterialLib(string mtlFile){string path = PathHelpers.GetFullPath(this.TexturePath, mtlFile);if (!File.Exists(path)){return;}using (var materialReader = new StreamReader(path)){ReadMaterial(materialReader);}}/// <summary>/// Loads the material library from a streamreader/// </summary>/// <param name="materialReader"></param>private void ReadMaterial(StreamReader materialReader){MaterialDefinition currentMaterial = null;while (!materialReader.EndOfStream){var line = materialReader.ReadLine();if (line == null){break;}line = line.Trim();if (line.StartsWith("#") || line.Length == 0){continue;}string keyword, value;SplitLine(line, out keyword, out value);switch (keyword.ToLower()){case "newmtl":if (value != null){if (this.Materials.ContainsKey(value)){currentMaterial = null;}else{currentMaterial = new MaterialDefinition(value);this.Materials.Add(value, currentMaterial);}}break;case "ka":if (currentMaterial != null && value != null){currentMaterial.Ambient = ColorParse(value);}break;case "kd":if (currentMaterial != null && value != null){currentMaterial.Diffuse = ColorParse(value);}break;case "ks":if (currentMaterial != null && value != null){currentMaterial.Specular = ColorParse(value);}break;case "ns":if (currentMaterial != null && value != null){currentMaterial.SpecularCoefficient = DoubleParse(value);}break;case "d":if (currentMaterial != null && value != null){currentMaterial.Dissolved = DoubleParse(value);}break;case "tr":if (!this.SkipTransparencyValues && currentMaterial != null && value != null){currentMaterial.Dissolved = DoubleParse(value);}break;case "illum":if (currentMaterial != null && value != null){currentMaterial.Illumination = int.Parse(value);}break;case "map_ka":if (currentMaterial != null){currentMaterial.AmbientMap = value;}break;case "map_kd":if (currentMaterial != null){currentMaterial.DiffuseMap = value;}break;case "map_ks":if (currentMaterial != null){currentMaterial.SpecularMap = value;}break;case "map_d":if (currentMaterial != null){currentMaterial.AlphaMap = value;}break;case "map_bump":case "bump":if (currentMaterial != null){currentMaterial.BumpMap = value;}break;}}}/// <summary>/// Sets the material for the current group./// </summary>/// <param name="materialName">/// The material name./// </param>private void SetMaterial(string materialName){this.CurrentGroup.Material = this.CurrentMaterial = this.GetMaterial(materialName);}/// <summary>/// Represents a group in the obj file./// </summary>public class Group{/// <summary>/// List of mesh builders./// </summary>private readonly List<MeshBuilder> meshBuilders;/// <summary>/// List of materials./// </summary>private readonly List<Material> materials;/// <summary>/// Initializes a new instance of the <see cref="Group"/> class./// </summary>/// <param name="name">/// The name of the group./// </param>/// <param name="material">The material of the group.</param>public Group(string name, Material material){this.Name = name;this.meshBuilders = new List<MeshBuilder>();this.materials = new List<Material>();this.AddMesh(material);}/// <summary>/// Sets the material./// </summary>/// <value>The material.</value>public Material Material{set{this.materials[this.materials.Count - 1] = value;}}/// <summary>/// Gets the mesh builder for the current mesh./// </summary>/// <value>The mesh builder.</value>public MeshBuilder MeshBuilder{get{return this.meshBuilders[this.meshBuilders.Count - 1];}}/// <summary>/// Gets or sets the group name./// </summary>/// <value>The name.</value>public string Name { get; set; }/// <summary>/// Adds a mesh./// </summary>/// <param name="material">The material of the group.</param>public void AddMesh(Material material){var meshBuilder = new MeshBuilder(true, true);this.meshBuilders.Add(meshBuilder);this.materials.Add(material);}/// <summary>/// Creates the models of the group./// </summary>/// <returns>The models.</returns>public IEnumerable<Model3D> CreateModels(){for (int i = 0; i < this.meshBuilders.Count; i++){DiffuseMaterial DefaultMaterial2 = new DiffuseMaterial();SolidColorBrush bursh = new SolidColorBrush(Color.FromRgb(23, 174, 204));bursh.Opacity = 1;DefaultMaterial2.Brush = bursh;//DefaultMaterial2.Color = Color.FromRgb(80, 88, 99);MaterialGroup materialgroup = new MaterialGroup();materialgroup.Children.Add(DefaultMaterial2);var material = this.materials[i];var mesh = this.meshBuilders[i].ToMesh();var model = new GeometryModel3D { Geometry = mesh,Material = materialgroup, BackMaterial = materialgroup };yield return model;}}}/// <summary>/// A material definition./// </summary>/// <remarks>/// The file format is documented in http://en.wikipedia.org/wiki/Material_Template_Library./// </remarks>public class MaterialDefinition{/// <summary>/// Initializes a new instance of the <see cref="MaterialDefinition" /> class./// </summary>/// <param name="name">The name.</param>public MaterialDefinition(string name){this.Name = name;this.Dissolved = 1.0;}/// <summary>/// Gets or sets the alpha map./// </summary>/// <value>The alpha map.</value>public string AlphaMap { get; set; }/// <summary>/// Gets or sets the ambient color./// </summary>/// <value>The ambient.</value>public Color Ambient { get; set; }/// <summary>/// Gets or sets the ambient map./// </summary>/// <value>The ambient map.</value>public string AmbientMap { get; set; }/// <summary>/// Gets or sets the bump map./// </summary>/// <value>The bump map.</value>public string BumpMap { get; set; }/// <summary>/// Gets or sets the diffuse color./// </summary>/// <value>The diffuse.</value>public Color Diffuse { get; set; }/// <summary>/// Gets or sets the diffuse map./// </summary>/// <value>The diffuse map.</value>public string DiffuseMap { get; set; }/// <summary>/// Gets or sets the opacity value./// </summary>/// <value>The opacity.</value>/// <remarks>/// 0.0 is transparent, 1.0 is opaque./// </remarks>public double Dissolved { get; set; }/// <summary>/// Gets or sets the illumination./// </summary>/// <value>The illumination.</value>public int Illumination { get; set; }/// <summary>/// Gets or sets the name of the material./// </summary>/// <value>/// The name./// </value>public string Name { get; set; }/// <summary>/// Gets or sets the specular color./// </summary>/// <value>The specular color.</value>public Color Specular { get; set; }/// <summary>/// Gets or sets the specular coefficient./// </summary>/// <value>The specular coefficient.</value>public double SpecularCoefficient { get; set; }/// <summary>/// Gets or sets the specular map./// </summary>/// <value>The specular map.</value>public string SpecularMap { get; set; }/// <summary>/// Gets or sets the material./// </summary>/// <value>The material.</value>public Material Material { get; set; }/// <summary>/// Gets the material from the specified path./// </summary>/// <param name="texturePath">/// The texture path./// </param>/// <returns>/// The material./// </returns>public Material GetMaterial(string texturePath){if (this.Material == null){this.Material = this.CreateMaterial(texturePath);}return this.Material;}/// <summary>/// Creates the material./// </summary>/// <param name="texturePath">The texture path.</param>/// <returns>A WPF material.</returns>private Material CreateMaterial(string texturePath){var mg = new MaterialGroup();mg.SetName(this.Name);// add the diffuse componentif (this.DiffuseMap == null){var diffuseBrush = new SolidColorBrush(this.Diffuse) { Opacity = this.Dissolved };mg.Children.Add(new DiffuseMaterial(diffuseBrush));}else{string path = PathHelpers.GetFullPath(texturePath, this.DiffuseMap);if (File.Exists(path)){mg.Children.Add(new DiffuseMaterial(this.CreateTextureBrush(path)));}}// add the ambient componentsif (this.AmbientMap == null){// ambient material is not supported by WPF?}else{string path = PathHelpers.GetFullPath(texturePath, this.AmbientMap);if (File.Exists(path)){mg.Children.Add(new EmissiveMaterial(this.CreateTextureBrush(path)));}}// add the specular componentif (this.Specular.R > 0 || this.Specular.G > 0 || this.Specular.B > 0){mg.Children.Add(new SpecularMaterial(new SolidColorBrush(this.Specular), this.SpecularCoefficient));}return mg.Children.Count != 1 ? mg : mg.Children[0];}/// <summary>/// Creates a texture brush./// </summary>/// <param name="path">The path.</param>/// <returns>The brush.</returns>private ImageBrush CreateTextureBrush(string path){var img = new BitmapImage(new Uri(path, UriKind.Relative));var textureBrush = new ImageBrush(img) { Opacity = this.Dissolved, ViewportUnits = BrushMappingMode.Absolute, TileMode = TileMode.Tile };return textureBrush;}}/// <summary>/// Path helpers./// </summary>private static class PathHelpers{/// <summary>/// Gets a full path./// </summary>/// <param name="basePath">/// The base path./// </param>/// <param name="path">/// The path./// </param>public static string GetFullPath(string basePath, string path){if (path.Length > 1&& (path[0] == Path.DirectorySeparatorChar || path[0] == Path.AltDirectorySeparatorChar)&& (path[1] != Path.DirectorySeparatorChar && path[1] != Path.AltDirectorySeparatorChar)){path = path.Substring(1);}return !string.IsNullOrWhiteSpace(basePath) ? Path.GetFullPath(Path.Combine(basePath, path)) : "";}}}

结果如图

解决helix.toolkit obj模型贴图查找失败导致的异常相关推荐

  1. c语言libjpeg处理图像,解决使用 libjpeg 保存图片时因磁盘写入失败导致程序退出的有关问题...

    0. libjpeg 介绍 libjpeg 是一个完全用C语言编写的库,包含了被广泛使用的JPEG解码.JPEG编码和其他的JPEG功能的实现.这个库由独立JPEG工作组维护. 参考:http://z ...

  2. 【Three.js】解决使用Three.js导入obj模型不可见问题详细记录

    问题描述: 近期在做三维重建项目,需要把最终生成的obj文件导入到web端浏览,这里使用的是three.js(另一个是babylon.js),但博主发现导入meshlab生成的obj时无法显示模型,但 ...

  3. Qualcomm AR SDK之替换模型(已解决模型贴图问题)

    ARVR技术交流群:129340649 欢迎加入! 求从事移动应用开发以及基于移动终端的AR应用开发的朋友,一起做一些事!有兴趣可以给我私信,谢谢! 1.将模型转换为.obj格式,这个通过很多三维软件 ...

  4. 解决在OpenGL中导入.obj模型所遇一些问题的方法

    解决在OpenGL中导入.obj模型所遇一些问题的方法 相对路径格式 "/"与"\" 相对路径起始 导入模型的限制 最近在学习 LearnOpenGL CN,学 ...

  5. 解决Unity模型贴图反转的问题

    解决Unity模型贴图反转的问题 设置shader的贴图属性:tiling x为-1 参考链接:https://www.cnblogs.com/vivid-stanley/p/5494218.html

  6. Html显示3D Obj模型(支持mtl纹理)的源码方案(2:一张图创建人脸模型)

    不要瞧不起html脚本语言,自从浏览器取消了flash,你是不是觉得html做不了炫酷的内容,错了!现在html支持OpenGL,支持直接渲染3D游戏.今天我们就来讲如何在html渲染3D 的Obj模 ...

  7. 解决导入obj模型时出现模型镂空的问题

    解决导入obj模型时出现模型镂空的问题 这实际上是因为导入的模型采用四边形而非三角形的面片,导致splish采样不全. 使用houdini的divide节点就能将任意面片转化为三角形面片.从而解决问题 ...

  8. threejs摩尔纹镜头拉远模型贴图出现摩尔纹,纹理贴图闪烁异常解决办法

    threejs镜头拉远模型贴图出现摩尔纹,纹理贴图闪烁异常解决办法 当threejs加载模型时,会遇到有些模型的贴图有密集网格形状,当有密集四方格类,或者其他形状密集条纹类的贴图时,就会出现摩尔纹. ...

  9. Maya打开.obj模型并为其贴图

    .obj模型在Maya中打开是没有贴图的,需要重新为其贴图. 首先将.obj模型导入Maya. 如下图: 接下来在菜单栏选择窗口,第二个下拉菜单(渲染编辑器),再选第三个下拉菜单(Hypershade ...

最新文章

  1. [好书推荐].计算机原理与设计——Verilog HDL版等;待续
  2. qt 拖拽 修改大小
  3. 初步了解Linux proc文件系统
  4. java点到原点距离_java-从经纬度坐标到欧氏距离(EuclideanDistance)完整代码
  5. Java InputStreamReader getEncoding()方法及示例
  6. mysql合并多条纪录字段_mysql合并多条记录的单个字段去一条记录
  7. 生产服务器怎么dmp堆栈信息,如何根据程序崩溃时的DMP文件使用WinDbg查找调用堆栈...
  8. linux下运行python_在Linux命令行终端中使用python的简单方法(推荐)
  9. 宝马纯电动i4原型车谍照曝光 预计2021年上市
  10. [转载]在instagram上面如何利用电脑来上传图片
  11. JavaScript初阶(十)---------- 数组
  12. unity现代人物含代码动画_Unity Animation--动画系统概述
  13. 用强化学习来玩Atari游戏(基于Tensorflow的深度Q学习模型)
  14. 无线充电Qi通信协议分析
  15. 游戏开发计划——数据元素设计(技能)
  16. 大唐移动骨干集体出走
  17. 如何制作CHM帮助文件
  18. 知乎热议:27岁没文凭、想自学编程,有机会成为程序员吗?互联网风口一去不复返了吗?
  19. c# 一个月中的工作日_在Excel中查找一个月中的第N个工作日
  20. kodi android 目录,如何在xbmc / kodi插件中创建多个目录?

热门文章

  1. Bobby Axelrod要回归Billions???
  2. 浪潮gs支持mysql么_浪潮gs中间件服务器,客户端,数据库sqlserver安装注意事项
  3. 什么是VR看房,VR看房的优势?
  4. UWB 定位技术方案选择
  5. 机房智能网络监控系统一体解决方案
  6. Spring之XML解析
  7. JavaScript实现圆周运动
  8. 最新系统漏洞--MipCMS服务器端请求伪造漏洞
  9. 大学物理实验计算机仿真 光电效应,光电效应仿真实验的教学探究
  10. C(X):vcruntime.h头文件