private void ReadMaterialEffect(ModelBase.MaterialDef matDef, string effectID) { effect matEffect = this.library_effects.effect.Where(eff => eff.id.Equals(effectID)).ElementAt(0); foreach (var profileCommon in matEffect.Items) { if (profileCommon.technique == null || profileCommon.technique.Item == null) continue; common_color_or_texture_type diffuse = null; common_float_or_param_type transparency = null; if ((profileCommon.technique.Item as effectFx_profile_abstractProfile_COMMONTechniquePhong) != null) { diffuse = (profileCommon.technique.Item as effectFx_profile_abstractProfile_COMMONTechniquePhong).diffuse; transparency = (profileCommon.technique.Item as effectFx_profile_abstractProfile_COMMONTechniquePhong).transparency; } else if ((profileCommon.technique.Item as effectFx_profile_abstractProfile_COMMONTechniqueLambert) != null) { diffuse = (profileCommon.technique.Item as effectFx_profile_abstractProfile_COMMONTechniqueLambert).diffuse; transparency = (profileCommon.technique.Item as effectFx_profile_abstractProfile_COMMONTechniqueLambert).transparency; } else if ((profileCommon.technique.Item as effectFx_profile_abstractProfile_COMMONTechniqueBlinn) != null) { diffuse = (profileCommon.technique.Item as effectFx_profile_abstractProfile_COMMONTechniqueBlinn).diffuse; transparency = (profileCommon.technique.Item as effectFx_profile_abstractProfile_COMMONTechniqueBlinn).transparency; } else if ((profileCommon.technique.Item as effectFx_profile_abstractProfile_COMMONTechniqueConstant) != null) { transparency = (profileCommon.technique.Item as effectFx_profile_abstractProfile_COMMONTechniqueConstant).transparency; } if (diffuse != null && diffuse.Item != null) { if ((diffuse.Item as common_color_or_texture_typeColor) != null) { var diffuseColour = diffuse.Item as common_color_or_texture_typeColor; matDef.m_Diffuse = Color.FromArgb((int)(diffuseColour.Values[0] * 255f), (int)(diffuseColour.Values[1] * 255f), (int)(diffuseColour.Values[2] * 255f)); } else if ((diffuse.Item as common_color_or_texture_typeTexture) != null) { var diffuseTexture = diffuse.Item as common_color_or_texture_typeTexture; string samplerID = diffuseTexture.texture; string surfaceID = null; string imageID = null; if (profileCommon.Items != null) { foreach (var item0 in profileCommon.Items) { var newparam = item0 as common_newparam_type; if (newparam == null || !newparam.sid.Equals(samplerID)) continue; surfaceID = (newparam.Item as fx_sampler2D_common).source; break; } foreach (var item0 in profileCommon.Items) { var newparam = item0 as common_newparam_type; if (newparam == null || !newparam.sid.Equals(surfaceID)) continue; imageID = (newparam.Item as fx_surface_common).init_from[0].Value; break; } } // Sometimes models reference a non-existant image ID; if that's the case, don't throw error, // just ignore and set colour to white. // Some exporters such as 3DS Max output the Image ID the texture.texture attribute. This is // wrong but I'm allowing it for convenience IEnumerable<image> matchingImage; if (this.library_images != null && this.library_images.image != null && (matchingImage = this.library_images.image.Where(img => img.id.Equals(imageID))).Count() > 0 || (matchingImage = this.library_images.image.Where(img => img.id.Equals(samplerID))).Count() > 0) { string texName = (string)matchingImage.ElementAt(0).Item; if (texName.Contains(m_ModelPath)) texName.Replace(m_ModelPath, ""); ModelBase.TextureDefBase texture = new ModelBase.TextureDefExternalBitmap( texName, m_ModelPath + Path.DirectorySeparatorChar + texName); AddTexture(texture, matDef); } else { Console.WriteLine("Warning: Material: " + matDef.m_ID + " referenced non-existant Image with ID: " + imageID); } matDef.m_Diffuse = Color.White; } } if (transparency != null && transparency.Item != null) { var value = (transparency.Item as common_float_or_param_typeFloat).Value; matDef.m_Alpha = (int)(value * 255f); } if (profileCommon.extra != null) { ReadEffectExtra(matDef, profileCommon.extra); } break; } if (matEffect.extra != null) { ReadEffectExtra(matDef, matEffect.extra); } }
private void LoadMaterials(string filename) { Stream fs; try { fs = File.OpenRead(filename); } catch { MessageBox.Show("Material library not found:\n\n" + filename + "\n\nA default white material will be used instead."); AddWhiteMat(); return; } StreamReader sr = new StreamReader(fs); string curmaterial = ""; string imagesNotFound = ""; string curline; while ((curline = sr.ReadLine()) != null) { curline = curline.Trim(); // skip empty lines and comments if (curline.Length < 1) { continue; } if (curline[0] == '#') { if (curline == "#Materials exported from Google Sketchup") { m_SketchupHack = true; } continue; } string[] parts = curline.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries); if (parts.Length < 1) { continue; } switch (parts[0]) { case "newmtl": // new material definition { if (parts.Length < 2) { continue; } curmaterial = parts[1]; ModelBase.MaterialDef mat = new ModelBase.MaterialDef(curmaterial); if (!m_Model.m_Materials.ContainsKey(curmaterial)) { m_Model.m_Materials.Add(curmaterial, mat); } } break; case "d": case "Tr": // opacity { if (parts.Length < 2) { continue; } float o = Helper.ParseFloat(parts[1]); if (m_SketchupHack) { o *= 31; } ModelBase.MaterialDef mat = (ModelBase.MaterialDef)m_Model.m_Materials[curmaterial]; mat.m_Alpha = (byte)(Math.Max(0, Math.Min(31, (int)(o * 31)))); } break; case "Kd": // diffuse colour { if (parts.Length < 4) { continue; } float r = Helper.ParseFloat(parts[1]); float g = Helper.ParseFloat(parts[2]); float b = Helper.ParseFloat(parts[3]); Color col = Color.FromArgb((int)(r * 255), (int)(g * 255), (int)(b * 255)); ModelBase.MaterialDef mat = (ModelBase.MaterialDef)m_Model.m_Materials[curmaterial]; mat.m_Diffuse = col; } break; case "Ka": // ambient colour { if (parts.Length < 4) { continue; } float r = Helper.ParseFloat(parts[1]); float g = Helper.ParseFloat(parts[2]); float b = Helper.ParseFloat(parts[3]); Color col = Color.FromArgb((int)(r * 255), (int)(g * 255), (int)(b * 255)); ModelBase.MaterialDef mat = (ModelBase.MaterialDef)m_Model.m_Materials[curmaterial]; mat.m_Ambient = col; } break; case "Ks": // specular colour { if (parts.Length < 4) { continue; } float r = Helper.ParseFloat(parts[1]); float g = Helper.ParseFloat(parts[2]); float b = Helper.ParseFloat(parts[3]); Color col = Color.FromArgb((int)(r * 255), (int)(g * 255), (int)(b * 255)); ModelBase.MaterialDef mat = (ModelBase.MaterialDef)m_Model.m_Materials[curmaterial]; mat.m_Specular = col; } break; case "map_Kd": case "mapKd": // diffuse map (texture) { string texname = curline.Substring(parts[0].Length + 1).Trim(); string fullPath = (File.Exists(texname)) ? texname : (m_ModelPath + Path.DirectorySeparatorChar + texname); ModelBase.TextureDefBase texture = new ModelBase.TextureDefExternalBitmap(texname, fullPath); AddTexture(texture, m_Model.m_Materials[curmaterial]); break; } case "PDF": { ModelBase.MaterialDef mat = (ModelBase.MaterialDef)m_Model.m_Materials[curmaterial]; switch (parts[1].ToLowerInvariant()) { case "front": mat.m_PolygonDrawingFace = ModelBase.MaterialDef.PolygonDrawingFace.Front; break; case "back": mat.m_PolygonDrawingFace = ModelBase.MaterialDef.PolygonDrawingFace.Back; break; case "both": mat.m_PolygonDrawingFace = ModelBase.MaterialDef.PolygonDrawingFace.FrontAndBack; break; default: goto case "front"; } } break; } } if (!imagesNotFound.Equals("")) { MessageBox.Show("The following images were not found:\n\n" + imagesNotFound); } sr.Close(); }