/// <summary> /// Creates the material /// </summary> void CreateMaterilas(Model model, Scene scene) { Debug.Assert(null != scene); { return; } int numMaterials = model.MaterialLib.Count; scene.Materials.Clear(); if (model.MaterialLib.Count == 0) { Debug.WriteLine("OBJ: no materials specified"); return; } for (int matIndex = 0; matIndex < numMaterials; matIndex++) { // Store material name // No material found, use the default material Material currentMaterial; if (!model.MaterialMap.TryGetValue(model.MaterialLib[matIndex], out currentMaterial)) { continue; } var mat = new AssimpSharp.Material(); mat.Name = currentMaterial.MaterialName; // convert illumination model ShadingMode sm = 0; switch (currentMaterial.IlluminationModel) { case 0: sm = ShadingMode.NoShading; break; case 1: sm = ShadingMode.Gouraud; break; case 2: sm = ShadingMode.Phong; break; default: sm = ShadingMode.Gouraud; Debug.WriteLine("OBJ: unexpected illumination model (0-2 recognized)"); break; } mat.ShadingMode = sm; // multiplying the specular exponent with 2 seems to yield better results currentMaterial.Shineness *= 4f; // Adding material colors mat.ColorAmbient = new Color4(currentMaterial.Ambient); mat.ColorDiffuse = new Color4(currentMaterial.Diffuse); mat.ColorSpecular = new Color4(currentMaterial.Specular); mat.ColorEmissive = new Color4(currentMaterial.Emissive); mat.Shininess = currentMaterial.Shineness; mat.Opacity = currentMaterial.Alpha; // Adding refraction index mat.Reflectivity = currentMaterial.IOR; // Adding textures if (!string.IsNullOrEmpty(currentMaterial.Texture)) { mat.TextureDiffuse = new TextureSlot() { TextureBase = currentMaterial.Texture }; if (currentMaterial.Clamp[(int)Material.TextureType.DiffuseType]) { AddTextureMappingModeProperty(mat, TextureType.Diffuse); } } if (!string.IsNullOrEmpty(currentMaterial.TextureAmbient)) { mat.TextureAmbient = new TextureSlot() { TextureBase = currentMaterial.TextureAmbient }; if (currentMaterial.Clamp[(int)Material.TextureType.AmbientType]) { AddTextureMappingModeProperty(mat, TextureType.Ambient); } } if (!string.IsNullOrEmpty(currentMaterial.TextureEmissive)) { mat.TextureAmbient = new TextureSlot() { TextureBase = currentMaterial.TextureEmissive }; } if (!string.IsNullOrEmpty(currentMaterial.TextureSpecular)) { mat.TextureSpecular = new TextureSlot() { TextureBase = currentMaterial.TextureSpecular }; if (currentMaterial.Clamp[(int)Material.TextureType.SpecularType]) { AddTextureMappingModeProperty(mat, TextureType.Specular); } } if (!string.IsNullOrEmpty(currentMaterial.TextureBump)) { mat.TextureHeight = new TextureSlot() { TextureBase = currentMaterial.TextureBump }; if (currentMaterial.Clamp[(int)Material.TextureType.BumpType]) { AddTextureMappingModeProperty(mat, TextureType.Height); } } if (!string.IsNullOrEmpty(currentMaterial.TextureNormal)) { mat.TextureNormals = new TextureSlot() { TextureBase = currentMaterial.TextureNormal }; if (currentMaterial.Clamp[(int)Material.TextureType.NormalType]) { AddTextureMappingModeProperty(mat, TextureType.Normals); } } if (!string.IsNullOrEmpty(currentMaterial.TextureDisp)) { mat.TextureDisplacement = new TextureSlot() { TextureBase = currentMaterial.TextureDisp }; if (currentMaterial.Clamp[(int)Material.TextureType.DispType]) { AddTextureMappingModeProperty(mat, TextureType.Displacement); } } if (!string.IsNullOrEmpty(currentMaterial.TextureOpacity)) { mat.TextureOpacity = new TextureSlot() { TextureBase = currentMaterial.TextureOpacity }; if (currentMaterial.Clamp[(int)Material.TextureType.OpacityType]) { AddTextureMappingModeProperty(mat, TextureType.Opacity); } } if (!string.IsNullOrEmpty(currentMaterial.TextureSpecularity)) { mat.TextureShininess = new TextureSlot() { TextureBase = currentMaterial.TextureSpecularity }; if (currentMaterial.Clamp[(int)Material.TextureType.SpecularityType]) { AddTextureMappingModeProperty(mat, TextureType.Shininess); } } // Store material property info in material array in scene scene.Materials.Add(mat); } // Test number of created materials. Debug.Assert(scene.Materials.Count == numMaterials); }
/// <summary> /// Converts all materials in the given array and stores them in the /// scene's material list. /// </summary> /// <param name="scene">The scene to hold the converted materials.</param> /// <param name="materials">The material array to convert.</param> protected void ConvertMaterials(AssimpSharp.Scene scene, List<AssimpSharp.XFile.Material> materials) { // count the non-referrer materials in the array var numNewMaterials = materials.Count(e => { return !e.IsReference; }); // resize the scene's material list to offer enough space for the new materials if (numNewMaterials > 0) { scene.Materials.Capacity = scene.Materials.Count + numNewMaterials; } // convert all the materials given in the array for (int a = 0; a < materials.Count; a++) { XFile.Material oldMat = materials[a]; if (oldMat.IsReference) { // find the material it refers to by name, and store its index for (int b = 0; b < scene.Materials.Count; b++) { var name = scene.Materials[b].Name; if (name == oldMat.Name) { oldMat.SceneIndex = a; break; } } if (oldMat.SceneIndex == int.MaxValue) { throw (new Exception()); oldMat.SceneIndex = 0; } continue; } var mat = new aiMaterial(); mat.Name = oldMat.Name; var shadeMode = (oldMat.SpecularExponent == 0.0f) ? AssimpSharp.ShadingMode.Gouraud : ShadingMode.Phong; mat.ShadingMode = shadeMode; mat.ColorEmissive = new Color4(oldMat.Emissive, 1); mat.ColorDiffuse = oldMat.Diffuse; mat.ColorSpecular = new Color4(oldMat.Specular, 1); mat.Shininess = oldMat.SpecularExponent; if (1 == oldMat.Textures.Count) { var otex = oldMat.Textures[0]; if (!string.IsNullOrEmpty(otex.Name)) { string tex = otex.Name; if (otex.IsNormalMap) { mat.TextureNormals = new TextureSlot() { TextureBase = tex }; } else { mat.TextureDiffuse = new TextureSlot() { TextureBase = tex }; } } } else { int iHM = 0, iNM = 0, iDM = 0, iSM = 0, iAM = 0, iEM = 0; for (int b = 0; b < oldMat.Textures.Count; b++) { var otex = oldMat.Textures[b]; var sz = otex.Name; if (string.IsNullOrEmpty(sz)) { continue; } int s = sz.LastIndexOf("\\/"); if (s == -1) { s = 0; } int sExt = sz.LastIndexOf('.'); if (sExt > 0) { sz = sz.Substring(0, sExt - 1) + '\0' + sz.Substring(sExt); } sz = sz.ToLower(); var tex = new TextureSlot() { TextureBase = oldMat.Textures[b].Name }; if (sz.Substring(s).Contains("bump") || sz.Substring(s).Contains("height")) { mat.TextureHeight = tex; } else if (otex.IsNormalMap || sz.Substring(s).Contains("normal") || sz.Substring(s).Contains("nm")) { mat.TextureNormals = tex; } else if (sz.Substring(s).Contains("spec") || sz.Substring(s).Contains("glanz")) { mat.TextureSpecular = tex; } else if (sz.Substring(s).Contains("ambi") || sz.Substring(s).Contains("env")) { mat.TextureAmbient = tex; } else if (sz.Substring(s).Contains("emissive") || sz.Substring(s).Contains("self")) { mat.TextureEmmisive = tex; } else { mat.TextureDiffuse = tex; } } } scene.Materials.Add(mat); //scene.Materials[scene.Materials.Count] = mat; oldMat.SceneIndex = scene.Materials.Count - 1; } }
/// <summary> /// Constructs the return data structure out of the imported data. /// </summary> /// <param name="scene">The scene to construct the return data in.</param> /// <param name="sdata">The imported data in the internal temporary representation.</param> protected void CreateDataRepresentationFromImport(AssimpSharp.Scene scene, Scene data) { // Read the global materials first so that meshes referring to them can find them later ConvertMaterials(scene, data.GlobalMaterial); // copy nodes, extracting meshes and materials on the way scene.RootNode = CreateNodes(scene, null, data.RootNode); // extract animations CreateAnimations(scene, data); // read the global meshes that were stored outside of any node if (data.GlobalMeshes.Count > 0) { // create a root node to hold them if there isn't any, yet if (scene.RootNode == null) { scene.RootNode = new AssimpSharp.Node(); scene.RootNode.Name = "$dummy_node"; } // convert all global meshes and store them in the root node. // If there was one before, the global meshes now suddenly have its transformation matrix... // Don't know what to do there, I don't want to insert another node under the present root node // just to avoid this. CreateMeshes(scene, scene.RootNode, data.GlobalMeshes); } if (scene.RootNode == null) { throw (new DeadlyImportError("No root node")); } // Convert everything to OpenGL space... it's the same operation as the conversion back, so we can reuse the step directly var convertProcess = new MakeLeftHandedProcess(); convertProcess.Execute(scene); var flipper = new FlipWindingOrderProcess(); flipper.Execute(scene); // finally: create a dummy material if not material was imported if (scene.Materials.Count == 0) { var mat = new aiMaterial(); mat.ShadingMode = ShadingMode.Gouraud; mat.ColorEmissive = new Color4(0, 0, 0, 1); mat.ColorSpecular = new Color4(0, 0, 0, 1); mat.ColorDiffuse = new Color4(0.5f, 0.5f, 0.5f, 1); mat.Shininess = 1.401298e-45f; scene.Materials.Add(mat); } }
private int ConvertMaterial(Material material, MeshGeometry mesh) { var props = material.Props; // generate empty output material var outMat = new aiMaterial(); this.MaterialsConverted[material] = this.Materials.Count; this.Materials.Add(outMat); // stip Material:: prefix string name = material.Name; if (name.Substring(0, 10) == "Material::") { name = name.Substring(10); } // set material name if not empty - this could happen // and there should be no key for it in this case. if (name.Length > 0) { outMat.Name = name; } // shading stuff and colors SetShadingPropertiesCommon(outMat, props); // texture assignments SetTextureProperties(outMat, material.Textures, mesh); SetTextureProperties(outMat, material.LayeredTextures, mesh); return this.Materials.Count - 1; }
private void TrySetTextureProperties(aiMaterial outMat, Dictionary<string, LayeredTexture> layeredTextures, string propName, aiTextureType target, MeshGeometry mesh) { LayeredTexture it; if (!layeredTextures.TryGetValue(propName, out it)) { return; } var tex = it.Texture; var path = tex.RelativeFilename; outMat.TextureSlotCollection[target].TextureBase = path; var uvTrafo = new AssimpSharp.UVTransform(); uvTrafo.Scaling = tex.UVScaling; uvTrafo.Translation = tex.UVTranslation; outMat.TextureSlotCollection[target].UVTransformBase = uvTrafo; var props = tex.Props; var uvIndex = 0; bool ok; var uvSet = PropertyHelper.PropertyGet<string>(props, "UVSet", out ok); if (ok) { if (uvSet != "default" && !string.IsNullOrEmpty(uvSet)) { var matIndex = Materials.IndexOf(outMat); uvIndex = -1; if (mesh == null) { foreach (var v in MeshesConverted) { var mesh_ = v.Key as MeshGeometry; if (mesh_ == null) { continue; } var mats = mesh_.MaterialIndices; if (!mats.Contains(matIndex)) { continue; } int index = -1; for (int i = 0; i < aiMesh.AI_MAX_NUMBER_OF_TEXTURECOORDS; i++) { if (mesh.GetTextureCoords(i).Count == 0) { break; } var name = mesh.GetTextureCoordChannelName(i); if (name == uvSet) { index = i; break; } } if (index == -1) { FBXImporter.LogWarn("did not find UV channel named " + uvSet + " in a mesh using this material"); continue; } if (uvIndex == -1) { uvIndex = index; } else { FBXImporter.LogWarn("the UV channel named " + uvSet + " appears at different positions in meshes, results will be wrong"); } } } else { int index = -1; for (int i = 0; i < aiMesh.AI_MAX_NUMBER_OF_TEXTURECOORDS; i++) { if (mesh.GetTextureCoords(i).Count == 0) { break; } var name = mesh.GetTextureCoordChannelName(i); if (name == uvSet) { index = i; break; } } if (index == -1) { FBXImporter.LogWarn("did not find UV channel named " + uvSet + " in a mesh using this material"); } if (uvIndex == -1) { uvIndex = index; } } if (uvIndex == -1) { FBXImporter.LogWarn("failed to resolve UV channel " + uvSet + ", using first UV channel"); uvIndex = 0; } } } outMat.TextureSlotCollection[target].UVWSrcBase = uvIndex; }
private void SetTextureProperties(aiMaterial outMat, Dictionary<string, LayeredTexture> layeredTextures, MeshGeometry mesh) { TrySetTextureProperties(outMat, layeredTextures, "DiffuseColor", aiTextureType.Diffuse, mesh); TrySetTextureProperties(outMat, layeredTextures, "AmbientColor", aiTextureType.Ambient, mesh); TrySetTextureProperties(outMat, layeredTextures, "EmissiveColor", aiTextureType.Emissive, mesh); TrySetTextureProperties(outMat, layeredTextures, "SpecularColor", aiTextureType.Specular, mesh); TrySetTextureProperties(outMat, layeredTextures, "TransparentColor", aiTextureType.Opacity, mesh); TrySetTextureProperties(outMat, layeredTextures, "ReflectionColor", aiTextureType.Reflection, mesh); TrySetTextureProperties(outMat, layeredTextures, "DisplacementColor", aiTextureType.Displacement, mesh); TrySetTextureProperties(outMat, layeredTextures, "NormalMap", aiTextureType.Normals, mesh); TrySetTextureProperties(outMat, layeredTextures, "Bump", aiTextureType.Height, mesh); TrySetTextureProperties(outMat, layeredTextures, "ShininessExponent", aiTextureType.Shininess, mesh); }
private void SetShadingPropertiesCommon(aiMaterial outMat, PropertyTable props) { bool ok; var diffuse = GetColorPropertyFromMaterial(props, "Diffuse", out ok); if (ok) { outMat.ColorDiffuse = new Color4(diffuse, 1.0f); } var emissive = GetColorPropertyFromMaterial(props, "Emissive", out ok); if (ok) { outMat.ColorEmissive = new Color4(emissive, 1.0f); } var ambient = GetColorPropertyFromMaterial(props, "Ambient", out ok); if (ok) { outMat.ColorAmbient = new Color4(ambient, 1.0f); } var specular = GetColorPropertyFromMaterial(props, "Specular", out ok); if (ok) { outMat.ColorSpecular = new Color4(specular, 1.0f); } float opacity = PropertyHelper.PropertyGet<float>(props, "Opacity", out ok); if (ok) { outMat.Opacity = opacity; } float reflectivity = PropertyHelper.PropertyGet<float>(props, "Reflectivity", out ok); if (ok) { outMat.Reflectivity = reflectivity; } float shininess = PropertyHelper.PropertyGet<float>(props, "Shininess", out ok); if (ok) { outMat.Shininess = shininess; } float shininessExponent = PropertyHelper.PropertyGet<float>(props, "ShininessExponent", out ok); if (ok) { outMat.ShininessStrength = shininessExponent; } }
private int GetDefaultMaterial() { if (DefaultMaterialIndex != 0) { return DefaultMaterialIndex - 1; } var outMat = new aiMaterial(); Materials.Add(outMat); var diffuse = new Color(0.8f, 0.8f, 0.8f, 0f); outMat.ColorDiffuse = diffuse; outMat.Name = aiMaterial.AI_DEFAULT_MATERIAL_NAME; this.DefaultMaterialIndex = Materials.Count; return DefaultMaterialIndex - 1; }