private void getAlphaMode(BabylonStandardMaterial babylonMaterial, out string alphaMode, out float?alphaCutoff) { // TODO: maybe we want to be able to handle both BabylonStandardMaterial and BabylonPBRMetallicRoughnessMaterial via the relevant fields being dropped to BabylonMaterial? // Serialization is going to be tricky, as we dont want BabylonStandardMaterial.alphaMode and BabylonStandardMaterial.alphaCutoff to be serialized (till we support it officially in-engine) alphaMode = null; alphaCutoff = null; switch (babylonMaterial.transparencyMode) { case (int)BabylonPBRMetallicRoughnessMaterial.TransparencyMode.OPAQUE: // reuse the BabylonPBRMaterialMetallicRoughness enum. alphaMode = GLTFMaterial.AlphaMode.OPAQUE.ToString(); break; case (int)BabylonPBRMetallicRoughnessMaterial.TransparencyMode.ALPHABLEND: alphaMode = GLTFMaterial.AlphaMode.BLEND.ToString(); break; case (int)BabylonPBRMetallicRoughnessMaterial.TransparencyMode.ALPHATEST: alphaCutoff = babylonMaterial.alphaCutOff; alphaMode = GLTFMaterial.AlphaMode.MASK.ToString(); break; case (int)BabylonPBRMetallicRoughnessMaterial.TransparencyMode.ALPHATESTANDBLEND: logger.RaiseWarning("GLTFExporter.Material | Alpha test and blend mode is not supported in glTF. Alpha blend is used instead.", 3); alphaMode = GLTFMaterial.AlphaMode.BLEND.ToString(); break; default: logger.RaiseWarning("GLTFExporter.Material | Unsupported transparency mode: " + babylonMaterial.transparencyMode, 3); break; } }
public void RegisterEmissive(GLTFTextureInfo TextureInfo, BabylonStandardMaterial babylonMaterial, float[] diffuse, float[] emissive) { string pathDiffuse; string pathEmissive; if (babylonMaterial.diffuseTexture != null) { pathDiffuse = babylonMaterial.diffuseTexture.originalPath; } else { pathDiffuse = "none"; } if (babylonMaterial.emissiveTexture != null) { pathEmissive = babylonMaterial.emissiveTexture.originalPath; } else { pathEmissive = "none"; } var _pair = CreatePair(pathDiffuse, pathEmissive, diffuse, emissive); _DicoEmissiveTextureComponent.Add(_pair, TextureInfo); }
public static void Init(MFnDependencyNode babylonAttributesDependencyNode, BabylonStandardMaterial babylonMaterial = null) { // Ensure all attributes are setup if (babylonAttributesDependencyNode.hasAttribute("babylonTransparencyMode") == false) { MGlobal.executeCommand($"addAttr -ln \"babylonTransparencyMode\" -nn \"Transparency Mode\" - at \"enum\" -en \"Opaque:Cutoff:Blend:\" {babylonAttributesDependencyNode.name};"); // Init alpha mode value based on material opacity if (babylonMaterial != null) { MGlobal.executeCommand($"setAttr \"{babylonAttributesDependencyNode.name}.babylonTransparencyMode\" {babylonMaterial.transparencyMode};"); } } if (babylonAttributesDependencyNode.hasAttribute("babylonBackfaceCulling") == false) { MGlobal.executeCommand($"addAttr -ln \"babylonBackfaceCulling\" -nn \"Backface Culling\" - at bool {babylonAttributesDependencyNode.name};"); MGlobal.executeCommand($"setAttr \"{babylonAttributesDependencyNode.name}.babylonBackfaceCulling\" 1;"); } if (babylonAttributesDependencyNode.hasAttribute("babylonUnlit") == false) { MGlobal.executeCommand($"addAttr -ln \"babylonUnlit\" -nn \"Unlit\" - at bool {babylonAttributesDependencyNode.name};"); } if (babylonAttributesDependencyNode.hasAttribute("babylonMaxSimultaneousLights") == false) { MGlobal.executeCommand($"addAttr -ln \"babylonMaxSimultaneousLights\" -nn \"Max Simultaneous Lights\" - at long -min 1 -dv 4 {babylonAttributesDependencyNode.name};"); } }
public GLTFTextureInfo GetRegisteredEmissive(BabylonStandardMaterial babylonMaterial, float[] diffuse, float[] emissive) { string pathDiffuse; string pathEmissive; if (babylonMaterial.diffuseTexture != null) { pathDiffuse = babylonMaterial.diffuseTexture.originalPath; } else { pathDiffuse = "none"; } if (babylonMaterial.emissiveTexture != null) { pathEmissive = babylonMaterial.emissiveTexture.originalPath; } else { pathEmissive = "none"; } var _pair = CreatePair(pathDiffuse, pathEmissive, diffuse, emissive); foreach (PairEmissiveDiffuse registeredText in _DicoEmissiveTextureComponent.Keys) { if (registeredText.Equals(_pair)) { return(_DicoEmissiveTextureComponent[registeredText]); } } return(null); }
public Dictionary <string, object> ExportCustomAttributeFromMaterial(BabylonStandardMaterial babylonMaterial) { var baseObject = new BaseObject(); baseObject.mFnTransform = null; baseObject.babylonMaterial = babylonMaterial; return(_ExportCustomUserAttributes(baseObject)); }
private void getAlphaMode(BabylonStandardMaterial babylonMaterial, out string alphaMode, out float?alphaCutoff) { if (babylonMaterial.diffuseTexture.hasAlpha) { alphaMode = GLTFMaterial.AlphaMode.BLEND.ToString(); } else { alphaMode = GLTFMaterial.AlphaMode.OPAQUE.ToString(); } alphaCutoff = null; }
private void getAlphaMode(BabylonStandardMaterial babylonMaterial, out string alphaMode, out float?alphaCutoff) { if (babylonMaterial.diffuseTexture != null && babylonMaterial.diffuseTexture.hasAlpha) { // TODO - Babylon standard material is assumed to useAlphaFromDiffuseTexture. If not, the alpha mode is a mask. alphaMode = GLTFMaterial.AlphaMode.BLEND.ToString(); } else { // glTF alpha mode default value is "OPAQUE" alphaMode = null; // GLTFMaterial.AlphaMode.OPAQUE.ToString(); } alphaCutoff = null; }
public static void Init(MFnDependencyNode babylonAttributesDependencyNode, BabylonStandardMaterial babylonMaterial = null) { babylonMaterialNodeBase.Init(babylonAttributesDependencyNode, babylonMaterial); if (babylonAttributesDependencyNode.hasAttribute("babylonTransparencyMode") == false) { MGlobal.executeCommand($"addAttr -ln \"babylonTransparencyMode\" -nn \"Transparency Mode\" -at \"enum\" -en \"Opaque:Cutoff:Blend:\" {babylonAttributesDependencyNode.name};"); } // Initialise attributes according to babylon material if (babylonMaterial != null) { // Init alpha mode value based on material opacity setAttributeValue(babylonAttributesDependencyNode.name + ".babylonTransparencyMode", babylonMaterial.transparencyMode); } }
private void getAlphaMode(BabylonStandardMaterial babylonMaterial, out string alphaMode, out float? alphaCutoff) { if (babylonMaterial.alpha != 1.0f || (babylonMaterial.diffuseTexture != null && babylonMaterial.diffuseTexture.hasAlpha) || babylonMaterial.opacityTexture != null) { // Babylon standard material is assumed to useAlphaFromDiffuseTexture. If not, the alpha mode is a mask. alphaMode = GLTFMaterial.AlphaMode.BLEND.ToString(); } else { alphaMode = GLTFMaterial.AlphaMode.OPAQUE.ToString(); } alphaCutoff = null; }
public TexturesPaths SetStandText(BabylonStandardMaterial babylonStandardMaterial) { var _StandText = new TexturesPaths(); if (babylonStandardMaterial.diffuseTexture != null) { _StandText.diffusePath = babylonStandardMaterial.diffuseTexture.originalPath; } else { _StandText.diffusePath = "none"; } if (babylonStandardMaterial.specularTexture != null) { _StandText.specularPath = babylonStandardMaterial.specularTexture.originalPath; } else { _StandText.specularPath = "none"; } if ((babylonStandardMaterial.diffuseTexture == null || babylonStandardMaterial.diffuseTexture.hasAlpha == false) && babylonStandardMaterial.opacityTexture != null) { _StandText.opacityPath = babylonStandardMaterial.opacityTexture.originalPath; } else { _StandText.opacityPath = "none"; } _StandText.diffuse = babylonStandardMaterial.diffuse; _StandText.opacity = babylonStandardMaterial.alpha; _StandText.specular = babylonStandardMaterial.specular; _StandText.glossiness = babylonStandardMaterial.specularPower; return(_StandText); }
private void ExportMaterial(IIGameMaterial materialNode, BabylonScene babylonScene) { var name = materialNode.MaterialName; var id = materialNode.MaxMaterial.GetGuid().ToString(); // Check if the material was already exported. The material id is unique. if (babylonScene.MaterialsList.FirstOrDefault(m => m.id == id) != null) { return; } RaiseMessage(name, 1); // --- prints --- #region prints { RaiseVerbose("materialNode.MaterialClass=" + materialNode.MaterialClass, 2); RaiseVerbose("materialNode.NumberOfTextureMaps=" + materialNode.NumberOfTextureMaps, 2); var propertyContainer = materialNode.IPropertyContainer; RaiseVerbose("propertyContainer=" + propertyContainer, 2); if (propertyContainer != null) { RaiseVerbose("propertyContainer.NumberOfProperties=" + propertyContainer.NumberOfProperties, 3); for (int i = 0; i < propertyContainer.NumberOfProperties; i++) { var prop = propertyContainer.GetProperty(i); if (prop != null) { RaiseVerbose("propertyContainer.GetProperty(" + i + ")=" + prop.Name, 3); switch (prop.GetType_) { case PropType.StringProp: string propertyString = ""; RaiseVerbose("prop.GetPropertyValue(ref propertyString, 0)=" + prop.GetPropertyValue(ref propertyString, 0), 4); RaiseVerbose("propertyString=" + propertyString, 4); break; case PropType.IntProp: int propertyInt = 0; RaiseVerbose("prop.GetPropertyValue(ref propertyInt, 0)=" + prop.GetPropertyValue(ref propertyInt, 0), 4); RaiseVerbose("propertyInt=" + propertyInt, 4); break; case PropType.FloatProp: float propertyFloat = 0; RaiseVerbose("prop.GetPropertyValue(ref propertyFloat, 0, true)=" + prop.GetPropertyValue(ref propertyFloat, 0, true), 4); RaiseVerbose("propertyFloat=" + propertyFloat, 4); RaiseVerbose("prop.GetPropertyValue(ref propertyFloat, 0, false)=" + prop.GetPropertyValue(ref propertyFloat, 0, false), 4); RaiseVerbose("propertyFloat=" + propertyFloat, 4); break; case PropType.Point3Prop: IPoint3 propertyPoint3 = Loader.Global.Point3.Create(0, 0, 0); RaiseVerbose("prop.GetPropertyValue(ref propertyPoint3, 0)=" + prop.GetPropertyValue(propertyPoint3, 0), 4); RaiseVerbose("propertyPoint3=" + Point3ToString(propertyPoint3), 4); break; case PropType.Point4Prop: IPoint4 propertyPoint4 = Loader.Global.Point4.Create(0, 0, 0, 0); RaiseVerbose("prop.GetPropertyValue(ref propertyPoint4, 0)=" + prop.GetPropertyValue(propertyPoint4, 0), 4); RaiseVerbose("propertyPoint4=" + Point4ToString(propertyPoint4), 4); break; case PropType.UnknownProp: default: RaiseVerbose("Unknown property type", 4); break; } } else { RaiseVerbose("propertyContainer.GetProperty(" + i + ") IS NULL", 3); } } } } #endregion if (materialNode.SubMaterialCount > 0) { var babylonMultimaterial = new BabylonMultiMaterial { name = name, id = id }; var guids = new List <string>(); for (var index = 0; index < materialNode.SubMaterialCount; index++) { var subMat = materialNode.GetSubMaterial(index); if (subMat != null) { guids.Add(subMat.MaxMaterial.GetGuid().ToString()); if (!referencedMaterials.Contains(subMat)) { referencedMaterials.Add(subMat); ExportMaterial(subMat, babylonScene); } } else { guids.Add(Guid.Empty.ToString()); } } babylonMultimaterial.materials = guids.ToArray(); babylonScene.MultiMaterialsList.Add(babylonMultimaterial); return; } var unlitProperty = materialNode.IPropertyContainer.QueryProperty("BabylonUnlit"); bool isUnlit = unlitProperty != null?unlitProperty.GetBoolValue() : false; var stdMat = materialNode.MaxMaterial.NumParamBlocks > 0 ? materialNode.MaxMaterial.GetParamBlock(0).Owner as IStdMat2 : null; if (stdMat != null) { var babylonMaterial = new BabylonStandardMaterial { name = name, id = id, isUnlit = isUnlit, diffuse = materialNode.MaxMaterial.GetDiffuse(0, false).ToArray(), alpha = 1.0f - materialNode.MaxMaterial.GetXParency(0, false) }; babylonMaterial.backFaceCulling = !stdMat.TwoSided; babylonMaterial.wireframe = stdMat.Wire; var isSelfIllumColor = materialNode.MaxMaterial.GetSelfIllumColorOn(0, false); var maxSpecularColor = materialNode.MaxMaterial.GetSpecular(0, false).ToArray(); if (isUnlit == false) { babylonMaterial.ambient = materialNode.MaxMaterial.GetAmbient(0, false).ToArray(); babylonMaterial.specular = maxSpecularColor.Multiply(materialNode.MaxMaterial.GetShinStr(0, false)); babylonMaterial.specularPower = materialNode.MaxMaterial.GetShininess(0, false) * 256; babylonMaterial.emissive = isSelfIllumColor ? materialNode.MaxMaterial.GetSelfIllumColor(0, false).ToArray() : materialNode.MaxMaterial.GetDiffuse(0, false).Scale(materialNode.MaxMaterial.GetSelfIllum(0, false)); // compute the pre-multiplied emissive color // If Self-Illumination color checkbox is checked // Then self-illumination is assumed to be pre-multiplied // Otherwise self-illumination needs to be multiplied with diffuse // linkEmissiveWithDiffuse attribute tells the Babylon engine to perform such multiplication babylonMaterial.linkEmissiveWithDiffuse = !isSelfIllumColor; // useEmissiveAsIllumination attribute tells the Babylon engine to use pre-multiplied emissive as illumination babylonMaterial.useEmissiveAsIllumination = isSelfIllumColor; // Store the emissive value (before multiplication) for gltf babylonMaterial.selfIllum = materialNode.MaxMaterial.GetSelfIllum(0, false); } // Textures BabylonFresnelParameters fresnelParameters; babylonMaterial.diffuseTexture = ExportTexture(stdMat, 1, out fresnelParameters, babylonScene); // Diffuse if (fresnelParameters != null) { babylonMaterial.diffuseFresnelParameters = fresnelParameters; } if ((babylonMaterial.alpha == 1.0f && babylonMaterial.opacityTexture == null) && babylonMaterial.diffuseTexture != null && (babylonMaterial.diffuseTexture.originalPath.EndsWith(".tif") || babylonMaterial.diffuseTexture.originalPath.EndsWith(".tiff")) && babylonMaterial.diffuseTexture.hasAlpha) { RaiseWarning($"Diffuse texture named {babylonMaterial.diffuseTexture.originalPath} is a .tif file and its Alpha Source is 'Image Alpha' by default.", 2); RaiseWarning($"If you don't want material to be in BLEND mode, set diffuse texture Alpha Source to 'None (Opaque)'", 2); } babylonMaterial.opacityTexture = ExportTexture(stdMat, 6, out fresnelParameters, babylonScene, false, true); // Opacity if (fresnelParameters != null) { babylonMaterial.opacityFresnelParameters = fresnelParameters; if (babylonMaterial.alpha == 1 && babylonMaterial.opacityTexture == null) { babylonMaterial.alpha = 0; } } if (isUnlit == false) { babylonMaterial.ambientTexture = ExportTexture(stdMat, 0, out fresnelParameters, babylonScene); // Ambient babylonMaterial.specularTexture = ExportSpecularTexture(materialNode, maxSpecularColor, babylonScene); babylonMaterial.emissiveTexture = ExportTexture(stdMat, 5, out fresnelParameters, babylonScene); // Emissive if (fresnelParameters != null) { babylonMaterial.emissiveFresnelParameters = fresnelParameters; if (babylonMaterial.emissive[0] == 0 && babylonMaterial.emissive[1] == 0 && babylonMaterial.emissive[2] == 0 && babylonMaterial.emissiveTexture == null) { babylonMaterial.emissive = new float[] { 1, 1, 1 }; } } babylonMaterial.bumpTexture = ExportTexture(stdMat, 8, out fresnelParameters, babylonScene); // Bump babylonMaterial.reflectionTexture = ExportTexture(stdMat, 9, out fresnelParameters, babylonScene, true); // Reflection if (fresnelParameters != null) { if (babylonMaterial.reflectionTexture == null) { RaiseWarning("Fallout cannot be used with reflection channel without a texture", 2); } else { babylonMaterial.reflectionFresnelParameters = fresnelParameters; } } } // Constraints if (babylonMaterial.diffuseTexture != null) { babylonMaterial.diffuse = new[] { 1.0f, 1.0f, 1.0f }; } if (babylonMaterial.emissiveTexture != null) { babylonMaterial.emissive = new float[] { 0, 0, 0 }; } if (babylonMaterial.opacityTexture != null && babylonMaterial.diffuseTexture != null && babylonMaterial.diffuseTexture.name == babylonMaterial.opacityTexture.name && babylonMaterial.diffuseTexture.hasAlpha && !babylonMaterial.opacityTexture.getAlphaFromRGB) { // This is a alpha testing purpose babylonMaterial.opacityTexture = null; babylonMaterial.diffuseTexture.hasAlpha = true; RaiseWarning("Opacity texture was removed because alpha from diffuse texture can be use instead", 2); RaiseWarning("If you do not want this behavior, just set Alpha Source = None on your diffuse texture", 2); } babylonScene.MaterialsList.Add(babylonMaterial); } else if (isPhysicalMaterial(materialNode)) { var propertyContainer = materialNode.IPropertyContainer; var babylonMaterial = new BabylonPBRMetallicRoughnessMaterial { name = name, id = id, isUnlit = isUnlit }; // --- Global --- // Alpha //var alphaFromXParency = 1.0f - materialNode.MaxMaterial.GetXParency(0, false); var alphaFromPropertyContainer = 1.0f - propertyContainer.GetFloatProperty(17); //RaiseMessage("alphaFromXParency=" + alphaFromXParency, 2); //RaiseMessage("alphaFromPropertyContainer=" + alphaFromPropertyContainer, 2); babylonMaterial.alpha = alphaFromPropertyContainer; babylonMaterial.baseColor = materialNode.MaxMaterial.GetDiffuse(0, false).ToArray(); var invertRoughness = propertyContainer.GetBoolProperty(5); if (isUnlit == false) { babylonMaterial.metallic = propertyContainer.GetFloatProperty(6); babylonMaterial.roughness = propertyContainer.GetFloatProperty(4); if (invertRoughness) { // Inverse roughness babylonMaterial.roughness = 1 - babylonMaterial.roughness; } // Self illumination is computed from emission color, luminance, temperature and weight babylonMaterial.emissive = materialNode.MaxMaterial.GetSelfIllumColorOn(0, false) ? materialNode.MaxMaterial.GetSelfIllumColor(0, false).ToArray() : materialNode.MaxMaterial.GetDiffuse(0, false).Scale(materialNode.MaxMaterial.GetSelfIllum(0, false)); } else { // Ignore specified roughness and metallic values babylonMaterial.metallic = 0; babylonMaterial.roughness = 0.9f; } // --- Textures --- // 1 - base color ; 9 - transparancy weight ITexmap colorTexmap = _getTexMap(materialNode, 1); ITexmap alphaTexmap = _getTexMap(materialNode, 9); babylonMaterial.baseTexture = ExportBaseColorAlphaTexture(colorTexmap, alphaTexmap, babylonMaterial.baseColor, babylonMaterial.alpha, babylonScene, name); if (isUnlit == false) { // Metallic, roughness, ambient occlusion ITexmap metallicTexmap = _getTexMap(materialNode, 5); ITexmap roughnessTexmap = _getTexMap(materialNode, 4); ITexmap ambientOcclusionTexmap = _getTexMap(materialNode, 6); // Use diffuse roughness map as ambient occlusion // Check if MR or ORM textures are already merged bool areTexturesAlreadyMerged = false; if (metallicTexmap != null && roughnessTexmap != null) { string sourcePathMetallic = getSourcePath(metallicTexmap); string sourcePathRoughness = getSourcePath(roughnessTexmap); if (sourcePathMetallic == sourcePathRoughness) { if (ambientOcclusionTexmap != null && exportParameters.mergeAOwithMR) { string sourcePathAmbientOcclusion = getSourcePath(ambientOcclusionTexmap); if (sourcePathMetallic == sourcePathAmbientOcclusion) { // Metallic, roughness and ambient occlusion are already merged RaiseVerbose("Metallic, roughness and ambient occlusion are already merged", 2); BabylonTexture ormTexture = ExportTexture(metallicTexmap, babylonScene); babylonMaterial.metallicRoughnessTexture = ormTexture; babylonMaterial.occlusionTexture = ormTexture; areTexturesAlreadyMerged = true; } } else { // Metallic and roughness are already merged RaiseVerbose("Metallic and roughness are already merged", 2); BabylonTexture ormTexture = ExportTexture(metallicTexmap, babylonScene); babylonMaterial.metallicRoughnessTexture = ormTexture; areTexturesAlreadyMerged = true; } } } if (areTexturesAlreadyMerged == false) { if (metallicTexmap != null || roughnessTexmap != null) { // Merge metallic, roughness and ambient occlusion RaiseVerbose("Merge metallic and roughness (and ambient occlusion if `mergeAOwithMR` is enabled)", 2); BabylonTexture ormTexture = ExportORMTexture(exportParameters.mergeAOwithMR ? ambientOcclusionTexmap : null, roughnessTexmap, metallicTexmap, babylonMaterial.metallic, babylonMaterial.roughness, babylonScene, invertRoughness); babylonMaterial.metallicRoughnessTexture = ormTexture; if (ambientOcclusionTexmap != null) { if (exportParameters.mergeAOwithMR) { babylonMaterial.occlusionTexture = ormTexture; } else { babylonMaterial.occlusionTexture = ExportPBRTexture(materialNode, 6, babylonScene); } } } else if (ambientOcclusionTexmap != null) { // Simply export occlusion texture RaiseVerbose("Simply export occlusion texture", 2); babylonMaterial.occlusionTexture = ExportTexture(ambientOcclusionTexmap, babylonScene); } } if (ambientOcclusionTexmap != null && !exportParameters.mergeAOwithMR && babylonMaterial.occlusionTexture == null) { RaiseVerbose("Exporting occlusion texture without merging with metallic roughness", 2); babylonMaterial.occlusionTexture = ExportTexture(ambientOcclusionTexmap, babylonScene); } var normalMapAmount = propertyContainer.GetFloatProperty(91); babylonMaterial.normalTexture = ExportPBRTexture(materialNode, 30, babylonScene, normalMapAmount); babylonMaterial.emissiveTexture = ExportPBRTexture(materialNode, 17, babylonScene); } if (babylonMaterial.alpha != 1.0f || (babylonMaterial.baseTexture != null && babylonMaterial.baseTexture.hasAlpha)) { var alphaTestProperty = materialNode.IPropertyContainer.QueryProperty("BabylonAlphaTest"); bool isAlphaTest = alphaTestProperty != null?alphaTestProperty.GetBoolValue() : false; babylonMaterial.transparencyMode = isAlphaTest ? (int)BabylonPBRMetallicRoughnessMaterial.TransparencyMode.ALPHATEST : (int)BabylonPBRMetallicRoughnessMaterial.TransparencyMode.ALPHABLEND; } if (babylonMaterial.emissiveTexture != null) { babylonMaterial.emissive = new[] { 1.0f, 1.0f, 1.0f }; } if (babylonMaterial.metallicRoughnessTexture != null) { babylonMaterial.metallic = 1.0f; babylonMaterial.roughness = 1.0f; } babylonScene.MaterialsList.Add(babylonMaterial); } else if (isArnoldMaterial(materialNode)) { var propertyContainer = materialNode.IPropertyContainer; var babylonMaterial = new BabylonPBRMetallicRoughnessMaterial { name = name, id = id, isUnlit = isUnlit }; // Alpha babylonMaterial.alpha = 1.0f - propertyContainer.GetFloatProperty(32); // Color: base * weight float[] baseColor = propertyContainer.GetPoint3Property(5).ToArray(); float baseWeight = propertyContainer.GetFloatProperty(2); babylonMaterial.baseColor = baseColor.Multiply(baseWeight); // Metallic & roughness bool invertRoughness = false; babylonMaterial.roughness = propertyContainer.GetFloatProperty(17); // specular_roughness babylonMaterial.metallic = propertyContainer.GetFloatProperty(29); // Emissive: emission_color * emission float[] emissionColor = propertyContainer.GetPoint3Property(94).ToArray(); float emissionWeight = propertyContainer.GetFloatProperty(91); babylonMaterial.emissive = emissionColor.Multiply(emissionWeight); // --- Textures --- // 1 - base_color ; 5 - diffuse_roughness ; 9 - metalness ; 10 - transparent ITexmap colorTexmap = _getTexMap(materialNode, 1); ITexmap alphaTexmap = _getTexMap(materialNode, 10); babylonMaterial.baseTexture = ExportBaseColorAlphaTexture(colorTexmap, alphaTexmap, babylonMaterial.baseColor, babylonMaterial.alpha, babylonScene, name); if (isUnlit == false) { // Metallic, roughness ITexmap metallicTexmap = _getTexMap(materialNode, 9); ITexmap roughnessTexmap = _getTexMap(materialNode, 5); // Check if MR textures are already merged bool areTexturesAlreadyMerged = false; if (metallicTexmap != null && roughnessTexmap != null) { string sourcePathMetallic = getSourcePath(metallicTexmap); string sourcePathRoughness = getSourcePath(roughnessTexmap); if (sourcePathMetallic == sourcePathRoughness) { // Metallic and roughness are already merged RaiseVerbose("Metallic and roughness are already merged", 2); BabylonTexture ormTexture = ExportTexture(metallicTexmap, babylonScene); babylonMaterial.metallicRoughnessTexture = ormTexture; // The already merged map is assumed to contain Ambient Occlusion in R channel babylonMaterial.occlusionTexture = ormTexture; areTexturesAlreadyMerged = true; } } if (areTexturesAlreadyMerged == false) { if (metallicTexmap != null || roughnessTexmap != null) { // Merge metallic, roughness RaiseVerbose("Merge metallic and roughness", 2); BabylonTexture ormTexture = ExportORMTexture(null, roughnessTexmap, metallicTexmap, babylonMaterial.metallic, babylonMaterial.roughness, babylonScene, invertRoughness); babylonMaterial.metallicRoughnessTexture = ormTexture; } } babylonMaterial.normalTexture = ExportPBRTexture(materialNode, 20, babylonScene); babylonMaterial.emissiveTexture = ExportPBRTexture(materialNode, 30, babylonScene); } // Constraints if (babylonMaterial.baseTexture != null) { babylonMaterial.baseColor = new[] { 1.0f, 1.0f, 1.0f }; babylonMaterial.alpha = 1.0f; } if (babylonMaterial.alpha != 1.0f || (babylonMaterial.baseTexture != null && babylonMaterial.baseTexture.hasAlpha)) { babylonMaterial.transparencyMode = (int)BabylonPBRMetallicRoughnessMaterial.TransparencyMode.ALPHABLEND; } if (babylonMaterial.emissiveTexture != null) { babylonMaterial.emissive = new[] { 1.0f, 1.0f, 1.0f }; } if (babylonMaterial.metallicRoughnessTexture != null) { babylonMaterial.metallic = 1.0f; babylonMaterial.roughness = 1.0f; } // Add the material to the scene babylonScene.MaterialsList.Add(babylonMaterial); } else { // isMaterialExportable check should prevent this to happen RaiseError("Unsupported material type: " + materialNode.MaterialClass, 2); } }
private void ExportMaterial(MFnDependencyNode materialDependencyNode, BabylonScene babylonScene) { MObject materialObject = materialDependencyNode.objectProperty; var name = materialDependencyNode.name; var id = materialDependencyNode.uuid().asString(); RaiseMessage(name, 1); RaiseVerbose("materialObject.hasFn(MFn.Type.kBlinn)=" + materialObject.hasFn(MFn.Type.kBlinn), 2); RaiseVerbose("materialObject.hasFn(MFn.Type.kPhong)=" + materialObject.hasFn(MFn.Type.kPhong), 2); RaiseVerbose("materialObject.hasFn(MFn.Type.kPhongExplorer)=" + materialObject.hasFn(MFn.Type.kPhongExplorer), 2); Print(materialDependencyNode, 2, "Print ExportMaterial materialDependencyNode"); // Standard material if (materialObject.hasFn(MFn.Type.kLambert)) { RaiseMessage("Lambert shader", 2); var lambertShader = new MFnLambertShader(materialObject); RaiseVerbose("typeId=" + lambertShader.typeId, 2); RaiseVerbose("typeName=" + lambertShader.typeName, 2); RaiseVerbose("color=" + lambertShader.color.toString(), 2); RaiseVerbose("transparency=" + lambertShader.transparency.toString(), 2); RaiseVerbose("ambientColor=" + lambertShader.ambientColor.toString(), 2); RaiseVerbose("incandescence=" + lambertShader.incandescence.toString(), 2); RaiseVerbose("diffuseCoeff=" + lambertShader.diffuseCoeff, 2); RaiseVerbose("translucenceCoeff=" + lambertShader.translucenceCoeff, 2); var babylonMaterial = new BabylonStandardMaterial { name = name, id = id, ambient = lambertShader.ambientColor.toArrayRGB(), diffuse = lambertShader.color.toArrayRGB(), emissive = lambertShader.incandescence.toArrayRGB(), alpha = 1.0f - lambertShader.transparency[0] }; // If transparency is not a shade of grey (shade of grey <=> R=G=B) if (lambertShader.transparency[0] != lambertShader.transparency[1] || lambertShader.transparency[0] != lambertShader.transparency[2]) { RaiseWarning("Transparency color is not a shade of grey. Only it's R channel is used.", 2); } // Convert transparency to opacity babylonMaterial.alpha = 1.0f - lambertShader.transparency[0]; // Specular power if (materialObject.hasFn(MFn.Type.kReflect)) { var reflectShader = new MFnReflectShader(materialObject); RaiseVerbose("specularColor=" + reflectShader.specularColor.toString(), 2); RaiseVerbose("reflectivity=" + reflectShader.reflectivity, 2); RaiseVerbose("reflectedColor=" + reflectShader.reflectedColor.toString(), 2); babylonMaterial.specular = reflectShader.specularColor.toArrayRGB(); if (materialObject.hasFn(MFn.Type.kBlinn)) { MFnBlinnShader blinnShader = new MFnBlinnShader(materialObject); babylonMaterial.specularPower = (1.0f - blinnShader.eccentricity) * 256; } else if (materialObject.hasFn(MFn.Type.kPhong)) { MFnPhongShader phongShader = new MFnPhongShader(materialObject); float glossiness = (float)Math.Log(phongShader.cosPower, 2) * 10; babylonMaterial.specularPower = glossiness / 100 * 256; } else if (materialObject.hasFn(MFn.Type.kPhongExplorer)) { MFnPhongEShader phongEShader = new MFnPhongEShader(materialObject); // No use of phongE.whiteness and phongE.highlightSize babylonMaterial.specularPower = (1.0f - phongEShader.roughness) * 256; } else { RaiseWarning("Unknown reflect shader type: " + reflectShader.typeName + ". Specular power is default 64. Consider using a Blinn or Phong shader instead.", 2); } } // TODO //babylonMaterial.backFaceCulling = !stdMat.TwoSided; //babylonMaterial.wireframe = stdMat.Wire; // Textures babylonMaterial.diffuseTexture = ExportTexture(materialDependencyNode, "color", babylonScene); babylonMaterial.ambientTexture = ExportTexture(materialDependencyNode, "ambientColor", babylonScene); babylonMaterial.emissiveTexture = ExportTexture(materialDependencyNode, "incandescence", babylonScene); babylonMaterial.bumpTexture = ExportTexture(materialDependencyNode, "normalCamera", babylonScene); // TODO - Convert transparency to opacity? babylonMaterial.opacityTexture = ExportTexture(materialDependencyNode, "transparency", babylonScene, false, true); if (materialObject.hasFn(MFn.Type.kReflect)) { babylonMaterial.specularTexture = ExportTexture(materialDependencyNode, "specularColor", babylonScene); babylonMaterial.reflectionTexture = ExportTexture(materialDependencyNode, "reflectedColor", babylonScene, true, false, true); } // Constraints if (babylonMaterial.diffuseTexture != null) { babylonMaterial.diffuse = new[] { 1.0f, 1.0f, 1.0f }; } if (babylonMaterial.emissiveTexture != null) { babylonMaterial.emissive = new float[] { 0, 0, 0 }; } babylonScene.MaterialsList.Add(babylonMaterial); } // PBR material else if (isPBRMaterial(materialDependencyNode)) { RaiseMessage("Stingray shader", 2); var babylonMaterial = new BabylonPBRMetallicRoughnessMaterial { name = name, id = id }; // --- Global --- // Color3 babylonMaterial.baseColor = materialDependencyNode.findPlug("base_color").asFloatArray(); // Alpha string opacityAttributeName = "opacity"; if (materialDependencyNode.hasAttribute(opacityAttributeName)) { float opacityAttributeValue = materialDependencyNode.findPlug(opacityAttributeName).asFloatProperty; babylonMaterial.alpha = 1.0f - opacityAttributeValue; } // Metallic & roughness babylonMaterial.metallic = materialDependencyNode.findPlug("metallic").asFloatProperty; babylonMaterial.roughness = materialDependencyNode.findPlug("roughness").asFloatProperty; // Emissive float emissiveIntensity = materialDependencyNode.findPlug("emissive_intensity").asFloatProperty; // Factor emissive color with emissive intensity emissiveIntensity = Tools.Clamp(emissiveIntensity, 0f, 1f); babylonMaterial.emissive = materialDependencyNode.findPlug("emissive").asFloatArray(); for (int i = 0; i < babylonMaterial.emissive.Length; i++) { babylonMaterial.emissive[i] *= emissiveIntensity; } // --- Textures --- // Base color & alpha bool useColorMap = materialDependencyNode.findPlug("use_color_map").asBoolProperty; bool useOpacityMap = false; string useOpacityMapAttributeName = "use_opacity_map"; if (materialDependencyNode.hasAttribute(useOpacityMapAttributeName)) { useOpacityMap = materialDependencyNode.findPlug(useOpacityMapAttributeName).asBoolProperty; } if (useColorMap || useOpacityMap) { // TODO - Force non use map to default value ? // Ex: if useOpacityMap == false, force alpha = 255 for all pixels. //babylonMaterial.baseTexture = ExportBaseColorAlphaTexture(materialDependencyNode, useColorMap, useOpacityMap, babylonMaterial.baseColor, babylonMaterial.alpha, babylonScene); babylonMaterial.baseTexture = ExportTexture(materialDependencyNode, "TEX_color_map", babylonScene, false, useOpacityMap); } // Metallic & roughness bool useMetallicMap = materialDependencyNode.findPlug("use_metallic_map").asBoolProperty; bool useRoughnessMap = materialDependencyNode.findPlug("use_roughness_map").asBoolProperty; babylonMaterial.metallicRoughnessTexture = ExportMetallicRoughnessTexture(materialDependencyNode, useMetallicMap, useRoughnessMap, babylonScene, name); if (materialDependencyNode.findPlug("use_normal_map").asBoolProperty) { babylonMaterial.normalTexture = ExportTexture(materialDependencyNode, "TEX_normal_map", babylonScene); } // Emissive bool useEmissiveMap = materialDependencyNode.findPlug("use_emissive_map").asBoolProperty; if (useEmissiveMap) { babylonMaterial.emissiveTexture = ExportTexture(materialDependencyNode, "TEX_emissive_map", babylonScene, false, false, false, emissiveIntensity); } // Ambient occlusion string useAOMapAttributeName = "use_ao_map"; if (materialDependencyNode.hasAttribute(useAOMapAttributeName) && materialDependencyNode.findPlug(useAOMapAttributeName).asBoolProperty) { babylonMaterial.occlusionTexture = ExportTexture(materialDependencyNode, "TEX_ao_map", babylonScene); } // Constraints if (useColorMap) { babylonMaterial.baseColor = new[] { 1.0f, 1.0f, 1.0f }; } if (useOpacityMap) { babylonMaterial.alpha = 1.0f; } if (babylonMaterial.alpha != 1.0f || (babylonMaterial.baseTexture != null && babylonMaterial.baseTexture.hasAlpha)) { babylonMaterial.transparencyMode = (int)BabylonPBRMetallicRoughnessMaterial.TransparencyMode.ALPHABLEND; } if (useMetallicMap) { babylonMaterial.metallic = 1.0f; } if (useRoughnessMap) { babylonMaterial.roughness = 1.0f; } if (useEmissiveMap) { babylonMaterial.emissive = new[] { 1.0f, 1.0f, 1.0f }; } babylonScene.MaterialsList.Add(babylonMaterial); } else { RaiseWarning("Unsupported material type '" + materialObject.apiType + "' for material named '" + materialDependencyNode.name + "'", 2); } }
private void ExportMaterial(MFnDependencyNode materialDependencyNode, BabylonScene babylonScene) { MObject materialObject = materialDependencyNode.objectProperty; var name = materialDependencyNode.name; var id = materialDependencyNode.uuid().asString(); RaiseMessage(name, 1); RaiseVerbose("materialObject.hasFn(MFn.Type.kBlinn)=" + materialObject.hasFn(MFn.Type.kBlinn), 2); RaiseVerbose("materialObject.hasFn(MFn.Type.kPhong)=" + materialObject.hasFn(MFn.Type.kPhong), 2); RaiseVerbose("materialObject.hasFn(MFn.Type.kPhongExplorer)=" + materialObject.hasFn(MFn.Type.kPhongExplorer), 2); Print(materialDependencyNode, 2, "Print ExportMaterial materialDependencyNode"); // Standard material if (materialObject.hasFn(MFn.Type.kLambert)) { if (materialObject.hasFn(MFn.Type.kBlinn)) { RaiseMessage("Blinn shader", 2); } else if (materialObject.hasFn(MFn.Type.kPhong)) { RaiseMessage("Phong shader", 2); } else if (materialObject.hasFn(MFn.Type.kPhongExplorer)) { RaiseMessage("Phong E shader", 2); } else { RaiseMessage("Lambert shader", 2); } var lambertShader = new MFnLambertShader(materialObject); RaiseVerbose("typeId=" + lambertShader.typeId, 2); RaiseVerbose("typeName=" + lambertShader.typeName, 2); RaiseVerbose("color=" + lambertShader.color.toString(), 2); RaiseVerbose("transparency=" + lambertShader.transparency.toString(), 2); RaiseVerbose("ambientColor=" + lambertShader.ambientColor.toString(), 2); RaiseVerbose("incandescence=" + lambertShader.incandescence.toString(), 2); RaiseVerbose("diffuseCoeff=" + lambertShader.diffuseCoeff, 2); RaiseVerbose("translucenceCoeff=" + lambertShader.translucenceCoeff, 2); var babylonMaterial = new BabylonStandardMaterial { name = name, id = id, diffuse = lambertShader.color.toArrayRGB(), alpha = 1.0f - lambertShader.transparency[0] }; // Maya ambient <=> babylon emissive babylonMaterial.emissive = lambertShader.ambientColor.toArrayRGB(); babylonMaterial.linkEmissiveWithDiffuse = true; // Incandescence (or Illumination) is not exported // If transparency is not a shade of grey (shade of grey <=> R=G=B) if (lambertShader.transparency[0] != lambertShader.transparency[1] || lambertShader.transparency[0] != lambertShader.transparency[2]) { RaiseWarning("Transparency color is not a shade of grey. Only it's R channel is used.", 2); } // Convert transparency to opacity babylonMaterial.alpha = 1.0f - lambertShader.transparency[0]; // Specular power if (materialObject.hasFn(MFn.Type.kReflect)) { var reflectShader = new MFnReflectShader(materialObject); RaiseVerbose("specularColor=" + reflectShader.specularColor.toString(), 2); RaiseVerbose("reflectivity=" + reflectShader.reflectivity, 2); RaiseVerbose("reflectedColor=" + reflectShader.reflectedColor.toString(), 2); babylonMaterial.specular = reflectShader.specularColor.toArrayRGB(); if (materialObject.hasFn(MFn.Type.kBlinn)) { MFnBlinnShader blinnShader = new MFnBlinnShader(materialObject); babylonMaterial.specularPower = (1.0f - blinnShader.eccentricity) * 256; } else if (materialObject.hasFn(MFn.Type.kPhong)) { MFnPhongShader phongShader = new MFnPhongShader(materialObject); float glossiness = (float)Math.Log(phongShader.cosPower, 2) * 10; babylonMaterial.specularPower = glossiness / 100 * 256; } else if (materialObject.hasFn(MFn.Type.kPhongExplorer)) { MFnPhongEShader phongEShader = new MFnPhongEShader(materialObject); // No use of phongE.whiteness and phongE.highlightSize babylonMaterial.specularPower = (1.0f - phongEShader.roughness) * 256; } else { RaiseWarning("Unknown reflect shader type: " + reflectShader.typeName + ". Specular power is default 64. Consider using a Blinn or Phong shader instead.", 2); } } // TODO //babylonMaterial.backFaceCulling = !stdMat.TwoSided; //babylonMaterial.wireframe = stdMat.Wire; // --- Textures --- babylonMaterial.diffuseTexture = ExportTexture(materialDependencyNode, "color", babylonScene); babylonMaterial.emissiveTexture = ExportTexture(materialDependencyNode, "ambientColor", babylonScene); // Maya ambient <=> babylon emissive babylonMaterial.bumpTexture = ExportTexture(materialDependencyNode, "normalCamera", babylonScene); babylonMaterial.opacityTexture = ExportTexture(materialDependencyNode, "transparency", babylonScene, false, true); if (materialObject.hasFn(MFn.Type.kReflect)) { babylonMaterial.specularTexture = ExportTexture(materialDependencyNode, "specularColor", babylonScene); babylonMaterial.reflectionTexture = ExportTexture(materialDependencyNode, "reflectedColor", babylonScene, true, false, true); } // Constraints if (babylonMaterial.diffuseTexture != null) { babylonMaterial.diffuse = new[] { 1.0f, 1.0f, 1.0f }; } if (babylonMaterial.emissiveTexture != null) { babylonMaterial.emissive = new float[] { 0, 0, 0 }; } babylonScene.MaterialsList.Add(babylonMaterial); } // Stingray PBS material else if (isStingrayPBSMaterial(materialDependencyNode)) { RaiseMessage("Stingray shader", 2); var babylonMaterial = new BabylonPBRMetallicRoughnessMaterial { name = name, id = id }; // --- Global --- // Color3 babylonMaterial.baseColor = materialDependencyNode.findPlug("base_color").asFloatArray(); // Alpha string opacityAttributeName = "opacity"; if (materialDependencyNode.hasAttribute(opacityAttributeName)) { float opacityAttributeValue = materialDependencyNode.findPlug(opacityAttributeName).asFloatProperty; babylonMaterial.alpha = 1.0f - opacityAttributeValue; } // Metallic & roughness babylonMaterial.metallic = materialDependencyNode.findPlug("metallic").asFloatProperty; babylonMaterial.roughness = materialDependencyNode.findPlug("roughness").asFloatProperty; // Emissive float emissiveIntensity = materialDependencyNode.findPlug("emissive_intensity").asFloatProperty; // Factor emissive color with emissive intensity emissiveIntensity = Tools.Clamp(emissiveIntensity, 0f, 1f); babylonMaterial.emissive = materialDependencyNode.findPlug("emissive").asFloatArray().Multiply(emissiveIntensity); // --- Textures --- // Base color & alpha bool useColorMap = materialDependencyNode.findPlug("use_color_map").asBoolProperty; bool useOpacityMap = false; string useOpacityMapAttributeName = "use_opacity_map"; if (materialDependencyNode.hasAttribute(useOpacityMapAttributeName)) { useOpacityMap = materialDependencyNode.findPlug(useOpacityMapAttributeName).asBoolProperty; } if (useColorMap || useOpacityMap) { // TODO - Force non use map to default value ? // Ex: if useOpacityMap == false, force alpha = 255 for all pixels. //babylonMaterial.baseTexture = ExportBaseColorAlphaTexture(materialDependencyNode, useColorMap, useOpacityMap, babylonMaterial.baseColor, babylonMaterial.alpha, babylonScene); babylonMaterial.baseTexture = ExportTexture(materialDependencyNode, "TEX_color_map", babylonScene, false, useOpacityMap); } // Metallic, roughness, ambient occlusion bool useMetallicMap = materialDependencyNode.findPlug("use_metallic_map").asBoolProperty; bool useRoughnessMap = materialDependencyNode.findPlug("use_roughness_map").asBoolProperty; string useAOMapAttributeName = "use_ao_map"; bool useAOMap = materialDependencyNode.hasAttribute(useAOMapAttributeName) && materialDependencyNode.findPlug(useAOMapAttributeName).asBoolProperty; MFnDependencyNode metallicTextureDependencyNode = useMetallicMap ? getTextureDependencyNode(materialDependencyNode, "TEX_metallic_map") : null; MFnDependencyNode roughnessTextureDependencyNode = useRoughnessMap ? getTextureDependencyNode(materialDependencyNode, "TEX_roughness_map") : null; MFnDependencyNode ambientOcclusionTextureDependencyNode = useAOMap ? getTextureDependencyNode(materialDependencyNode, "TEX_ao_map") : null; // Check if MR or ORM textures are already merged bool areTexturesAlreadyMerged = false; if (metallicTextureDependencyNode != null && roughnessTextureDependencyNode != null) { string sourcePathMetallic = getSourcePathFromFileTexture(metallicTextureDependencyNode); string sourcePathRoughness = getSourcePathFromFileTexture(roughnessTextureDependencyNode); if (sourcePathMetallic == sourcePathRoughness) { if (ambientOcclusionTextureDependencyNode != null) { string sourcePathAmbientOcclusion = getSourcePathFromFileTexture(ambientOcclusionTextureDependencyNode); if (sourcePathMetallic == sourcePathAmbientOcclusion) { // Metallic, roughness and ambient occlusion are already merged RaiseVerbose("Metallic, roughness and ambient occlusion are already merged", 2); BabylonTexture ormTexture = ExportTexture(metallicTextureDependencyNode, babylonScene); babylonMaterial.metallicRoughnessTexture = ormTexture; babylonMaterial.occlusionTexture = ormTexture; areTexturesAlreadyMerged = true; } } else { // Metallic and roughness are already merged RaiseVerbose("Metallic and roughness are already merged", 2); BabylonTexture ormTexture = ExportTexture(metallicTextureDependencyNode, babylonScene); babylonMaterial.metallicRoughnessTexture = ormTexture; areTexturesAlreadyMerged = true; } } } if (areTexturesAlreadyMerged == false) { if (metallicTextureDependencyNode != null || roughnessTextureDependencyNode != null) { // Merge metallic, roughness and ambient occlusion RaiseVerbose("Merge metallic, roughness and ambient occlusion", 2); BabylonTexture ormTexture = ExportORMTexture(babylonScene, metallicTextureDependencyNode, roughnessTextureDependencyNode, ambientOcclusionTextureDependencyNode, babylonMaterial.metallic, babylonMaterial.roughness); babylonMaterial.metallicRoughnessTexture = ormTexture; if (ambientOcclusionTextureDependencyNode != null) { babylonMaterial.occlusionTexture = ormTexture; } } else if (ambientOcclusionTextureDependencyNode != null) { // Simply export occlusion texture RaiseVerbose("Simply export occlusion texture", 2); babylonMaterial.occlusionTexture = ExportTexture(ambientOcclusionTextureDependencyNode, babylonScene); } } // Normal if (materialDependencyNode.findPlug("use_normal_map").asBoolProperty) { babylonMaterial.normalTexture = ExportTexture(materialDependencyNode, "TEX_normal_map", babylonScene); } // Emissive bool useEmissiveMap = materialDependencyNode.findPlug("use_emissive_map").asBoolProperty; if (useEmissiveMap) { babylonMaterial.emissiveTexture = ExportTexture(materialDependencyNode, "TEX_emissive_map", babylonScene, false, false, false, emissiveIntensity); } // Constraints if (useColorMap) { babylonMaterial.baseColor = new[] { 1.0f, 1.0f, 1.0f }; } if (useOpacityMap) { babylonMaterial.alpha = 1.0f; } if (babylonMaterial.alpha != 1.0f || (babylonMaterial.baseTexture != null && babylonMaterial.baseTexture.hasAlpha)) { babylonMaterial.transparencyMode = (int)BabylonPBRMetallicRoughnessMaterial.TransparencyMode.ALPHABLEND; } if (useMetallicMap) { babylonMaterial.metallic = 1.0f; } if (useRoughnessMap) { babylonMaterial.roughness = 1.0f; } if (useEmissiveMap) { babylonMaterial.emissive = new[] { 1.0f, 1.0f, 1.0f }; } babylonScene.MaterialsList.Add(babylonMaterial); } // Arnold Ai Standard Surface else if (isAiStandardSurface(materialDependencyNode)) { RaiseMessage("Ai Standard Surface shader", 2); var babylonMaterial = new BabylonPBRMetallicRoughnessMaterial { name = name, id = id }; // --- Global --- // Color3 float baseWeight = materialDependencyNode.findPlug("base").asFloatProperty; float[] baseColor = materialDependencyNode.findPlug("baseColor").asFloatArray(); babylonMaterial.baseColor = baseColor.Multiply(baseWeight); // Alpha MaterialDuplicationData materialDuplicationData = materialDuplicationDatas[id]; // If at least one mesh is Transparent and is using this material either directly or as a sub material if (materialDuplicationData.isArnoldTransparent()) { float[] opacityAttributeValue = materialDependencyNode.findPlug("opacity").asFloatArray(); babylonMaterial.alpha = opacityAttributeValue[0]; } else { // Do not bother about alpha babylonMaterial.alpha = 1.0f; } // Metallic & roughness babylonMaterial.metallic = materialDependencyNode.findPlug("metalness").asFloatProperty; babylonMaterial.roughness = materialDependencyNode.findPlug("specularRoughness").asFloatProperty; // Emissive float emissionWeight = materialDependencyNode.findPlug("emission").asFloatProperty; babylonMaterial.emissive = materialDependencyNode.findPlug("emissionColor").asFloatArray().Multiply(emissionWeight); // --- Textures --- // Base color & alpha if (materialDuplicationData.isArnoldTransparent()) { MFnDependencyNode baseColorTextureDependencyNode = getTextureDependencyNode(materialDependencyNode, "baseColor"); MFnDependencyNode opacityTextureDependencyNode = getTextureDependencyNode(materialDependencyNode, "opacity"); if (baseColorTextureDependencyNode != null && opacityTextureDependencyNode != null && getSourcePathFromFileTexture(baseColorTextureDependencyNode) == getSourcePathFromFileTexture(opacityTextureDependencyNode)) { // If the same file is used for base color and opacity // Base color and alpha are already merged into a single file babylonMaterial.baseTexture = ExportTexture(baseColorTextureDependencyNode, babylonScene, false, true); } else { // Base color and alpha files need to be merged into a single file Color _baseColor = Color.FromArgb((int)baseColor[0] * 255, (int)baseColor[1] * 255, (int)baseColor[2] * 255); babylonMaterial.baseTexture = ExportBaseColorAlphaTexture(baseColorTextureDependencyNode, opacityTextureDependencyNode, babylonScene, name, _baseColor, babylonMaterial.alpha); } } else { // Base color only // Do not bother about alpha babylonMaterial.baseTexture = ExportTexture(materialDependencyNode, "baseColor", babylonScene); } // Metallic & roughness MFnDependencyNode metallicTextureDependencyNode = getTextureDependencyNode(materialDependencyNode, "metalness"); MFnDependencyNode roughnessTextureDependencyNode = getTextureDependencyNode(materialDependencyNode, "specularRoughness"); if (metallicTextureDependencyNode != null && roughnessTextureDependencyNode != null && getSourcePathFromFileTexture(metallicTextureDependencyNode) == getSourcePathFromFileTexture(roughnessTextureDependencyNode)) { // If the same file is used for metallic and roughness // Then we assume it's an ORM file (Red=Occlusion, Green=Roughness, Blue=Metallic) // Metallic and roughness are already merged into a single file babylonMaterial.metallicRoughnessTexture = ExportTexture(metallicTextureDependencyNode, babylonScene); // Use same file for Ambient occlusion babylonMaterial.occlusionTexture = babylonMaterial.metallicRoughnessTexture; } else { // Metallic and roughness files need to be merged into a single file // Occlusion texture is not exported since aiStandardSurface material doesn't provide input for it babylonMaterial.metallicRoughnessTexture = ExportORMTexture(babylonScene, metallicTextureDependencyNode, roughnessTextureDependencyNode, null, babylonMaterial.metallic, babylonMaterial.roughness); } // Normal babylonMaterial.normalTexture = ExportTexture(materialDependencyNode, "normalCamera", babylonScene); // Emissive babylonMaterial.emissiveTexture = ExportTexture(materialDependencyNode, "emissionColor", babylonScene); // Constraints if (babylonMaterial.baseTexture != null) { babylonMaterial.baseColor = new[] { baseWeight, baseWeight, baseWeight }; babylonMaterial.alpha = 1.0f; } if (babylonMaterial.metallicRoughnessTexture != null) { babylonMaterial.metallic = 1.0f; babylonMaterial.roughness = 1.0f; } if (babylonMaterial.emissiveTexture != null) { babylonMaterial.emissive = new[] { emissionWeight, emissionWeight, emissionWeight }; } // If this material is containing alpha data if (babylonMaterial.alpha != 1.0f || (babylonMaterial.baseTexture != null && babylonMaterial.baseTexture.hasAlpha)) { babylonMaterial.transparencyMode = (int)BabylonPBRMetallicRoughnessMaterial.TransparencyMode.ALPHABLEND; // If this material is assigned to both Transparent and Opaque meshes (either directly or as a sub material) if (materialDuplicationData.isDuplicationRequired()) { // Duplicate material BabylonPBRMetallicRoughnessMaterial babylonMaterialCloned = DuplicateMaterial(babylonMaterial, materialDuplicationData); // Store duplicated material too babylonScene.MaterialsList.Add(babylonMaterialCloned); } } babylonScene.MaterialsList.Add(babylonMaterial); } else { RaiseWarning("Unsupported material type '" + materialObject.apiType + "' for material named '" + materialDependencyNode.name + "'", 2); } }
private void ExportMaterial(IIGameMaterial materialNode, BabylonScene babylonScene) { var name = materialNode.MaterialName; var id = materialNode.MaxMaterial.GetGuid().ToString(); RaiseMessage(name, 1); if (materialNode.SubMaterialCount > 0) { var babylonMultimaterial = new BabylonMultiMaterial { name = name, id = id }; var guids = new List <string>(); for (var index = 0; index < materialNode.SubMaterialCount; index++) { var subMat = materialNode.GetSubMaterial(index); if (subMat != null) { guids.Add(subMat.MaxMaterial.GetGuid().ToString()); if (!referencedMaterials.Contains(subMat)) { referencedMaterials.Add(subMat); ExportMaterial(subMat, babylonScene); } } else { guids.Add(Guid.Empty.ToString()); } } babylonMultimaterial.materials = guids.ToArray(); babylonScene.MultiMaterialsList.Add(babylonMultimaterial); return; } var babylonMaterial = new BabylonStandardMaterial { name = name, id = id, ambient = materialNode.MaxMaterial.GetAmbient(0, false).ToArray(), diffuse = materialNode.MaxMaterial.GetDiffuse(0, false).ToArray(), specular = materialNode.MaxMaterial.GetSpecular(0, false).Scale(materialNode.MaxMaterial.GetShinStr(0, false)), specularPower = materialNode.MaxMaterial.GetShininess(0, false) * 256, emissive = materialNode.MaxMaterial.GetSelfIllumColorOn(0, false) ? materialNode.MaxMaterial.GetSelfIllumColor(0, false).ToArray() : materialNode.MaxMaterial.GetDiffuse(0, false).Scale(materialNode.MaxMaterial.GetSelfIllum(0, false)), alpha = 1.0f - materialNode.MaxMaterial.GetXParency(0, false) }; var stdMat = materialNode.MaxMaterial.GetParamBlock(0).Owner as IStdMat2; if (stdMat != null) { babylonMaterial.backFaceCulling = !stdMat.TwoSided; babylonMaterial.wireframe = stdMat.Wire; // Textures BabylonFresnelParameters fresnelParameters; babylonMaterial.ambientTexture = ExportTexture(stdMat, 0, out fresnelParameters, babylonScene); // Ambient babylonMaterial.diffuseTexture = ExportTexture(stdMat, 1, out fresnelParameters, babylonScene); // Diffuse if (fresnelParameters != null) { babylonMaterial.diffuseFresnelParameters = fresnelParameters; } babylonMaterial.specularTexture = ExportTexture(stdMat, 2, out fresnelParameters, babylonScene); // Specular babylonMaterial.emissiveTexture = ExportTexture(stdMat, 5, out fresnelParameters, babylonScene); // Emissive if (fresnelParameters != null) { babylonMaterial.emissiveFresnelParameters = fresnelParameters; if (babylonMaterial.emissive[0] == 0 && babylonMaterial.emissive[1] == 0 && babylonMaterial.emissive[2] == 0 && babylonMaterial.emissiveTexture == null) { babylonMaterial.emissive = new float[] { 1, 1, 1 }; } } babylonMaterial.opacityTexture = ExportTexture(stdMat, 6, out fresnelParameters, babylonScene, false, true); // Opacity if (fresnelParameters != null) { babylonMaterial.opacityFresnelParameters = fresnelParameters; if (babylonMaterial.alpha == 1 && babylonMaterial.opacityTexture == null) { babylonMaterial.alpha = 0; } } babylonMaterial.bumpTexture = ExportTexture(stdMat, 8, out fresnelParameters, babylonScene); // Bump babylonMaterial.reflectionTexture = ExportTexture(stdMat, 9, out fresnelParameters, babylonScene, true); // Reflection if (fresnelParameters != null) { if (babylonMaterial.reflectionTexture == null) { RaiseWarning("Fallout cannot be used with reflection channel without a texture", 2); } else { babylonMaterial.reflectionFresnelParameters = fresnelParameters; } } // Constraints if (babylonMaterial.diffuseTexture != null) { babylonMaterial.diffuse = new[] { 1.0f, 1.0f, 1.0f }; } if (babylonMaterial.emissiveTexture != null) { babylonMaterial.emissive = new float[] { 0, 0, 0 }; } if (babylonMaterial.opacityTexture != null && babylonMaterial.diffuseTexture != null && babylonMaterial.diffuseTexture.name == babylonMaterial.opacityTexture.name && babylonMaterial.diffuseTexture.hasAlpha && !babylonMaterial.opacityTexture.getAlphaFromRGB) { // This is a alpha testing purpose babylonMaterial.opacityTexture = null; babylonMaterial.diffuseTexture.hasAlpha = true; RaiseWarning("Opacity texture was removed because alpha from diffuse texture can be use instead", 2); RaiseWarning("If you do not want this behavior, just set Alpha Source = None on your diffuse texture", 2); } } babylonScene.MaterialsList.Add(babylonMaterial); }
private GLTFTextureInfo ExportEmissiveTexture(BabylonStandardMaterial babylonMaterial, GLTF gltf, float[] defaultEmissive, float[] defaultDiffuse) { // Use one as a reference for UVs parameters var babylonTexture = babylonMaterial.emissiveTexture != null ? babylonMaterial.emissiveTexture : babylonMaterial.diffuseTexture; if (babylonTexture == null) { return(null); } // Anticipate if a black texture is going to be export if (babylonMaterial.emissiveTexture == null && defaultEmissive.IsAlmostEqualTo(new float[] { 0, 0, 0 }, 0)) { return(null); } // Check if the texture has already been exported if (GetRegisteredEmissive(babylonMaterial, defaultDiffuse, defaultEmissive) != null) { return(GetRegisteredEmissive(babylonMaterial, defaultDiffuse, defaultEmissive)); } Bitmap emissivePremultipliedBitmap = null; if (exportParameters.writeTextures) { // Emissive Bitmap emissiveBitmap = null; if (babylonMaterial.emissiveTexture != null) { emissiveBitmap = TextureUtilities.LoadTexture(babylonMaterial.emissiveTexture.originalPath, logger); } // Diffuse Bitmap diffuseBitmap = null; if (babylonMaterial.diffuseTexture != null) { diffuseBitmap = TextureUtilities.LoadTexture(babylonMaterial.diffuseTexture.originalPath, logger); } if (emissiveBitmap != null || diffuseBitmap != null) { // Retreive dimensions int width = 0; int height = 0; var haveSameDimensions = TextureUtilities.GetMinimalBitmapDimensions(out width, out height, emissiveBitmap, diffuseBitmap); if (!haveSameDimensions) { logger.RaiseError("Emissive and diffuse maps should have same dimensions", 2); } // Create pre-multiplied emissive map emissivePremultipliedBitmap = new Bitmap(width, height); for (int x = 0; x < width; x++) { for (int y = 0; y < height; y++) { var _emissive = emissiveBitmap != null?emissiveBitmap.GetPixel(x, y).toArrayRGB().Multiply(1f / 255.0f) : defaultEmissive; var _diffuse = diffuseBitmap != null?diffuseBitmap.GetPixel(x, y).toArrayRGB().Multiply(1f / 255.0f) : defaultDiffuse; var emissivePremultiplied = _emissive.Multiply(_diffuse); Color colorEmissivePremultiplied = Color.FromArgb( (int)(emissivePremultiplied[0] * 255), (int)(emissivePremultiplied[1] * 255), (int)(emissivePremultiplied[2] * 255) ); emissivePremultipliedBitmap.SetPixel(x, y, colorEmissivePremultiplied); } } } } var emissiveTextureInfo = ExportBitmapTexture(gltf, babylonTexture, emissivePremultipliedBitmap); // Register the texture for optimisation RegisterEmissive(emissiveTextureInfo, babylonMaterial, defaultDiffuse, defaultEmissive); return(emissiveTextureInfo); }
private void ExportCommonBabylonAttributes(MFnDependencyNode babylonAttributesDependencyNode, BabylonStandardMaterial babylonMaterial) { ExportCommonBabylonAttributes0(babylonAttributesDependencyNode, babylonMaterial); if (babylonAttributesDependencyNode.hasAttribute("babylonTransparencyMode")) { int v = babylonAttributesDependencyNode.findPlug("babylonTransparencyMode").asInt(); RaiseVerbose($"babylonTransparencyMode={v}", 3); babylonMaterial.transparencyMode = v; } }
private GLTFTextureInfo ExportEmissiveTexture(BabylonStandardMaterial babylonMaterial, GLTF gltf, float[] defaultEmissive, float[] defaultDiffuse) { // Use one as a reference for UVs parameters var babylonTexture = babylonMaterial.emissiveTexture != null ? babylonMaterial.emissiveTexture : babylonMaterial.diffuseTexture; if (babylonTexture == null) { return null; } Bitmap emissivePremultipliedBitmap = null; if (CopyTexturesToOutput) { // Emissive Bitmap emissiveBitmap = null; if (babylonMaterial.emissiveTexture != null) { emissiveBitmap = LoadTexture(babylonMaterial.emissiveTexture.originalPath); } // Diffuse Bitmap diffuseBitmap = null; if (babylonMaterial.diffuseTexture != null) { diffuseBitmap = LoadTexture(babylonMaterial.diffuseTexture.originalPath); } if (emissiveBitmap != null || diffuseBitmap != null) { // Retreive dimensions int width = 0; int height = 0; var haveSameDimensions = _getMinimalBitmapDimensions(out width, out height, emissiveBitmap, diffuseBitmap); if (!haveSameDimensions) { RaiseError("Emissive and diffuse maps should have same dimensions", 2); } // Create pre-multiplied emissive map emissivePremultipliedBitmap = new Bitmap(width, height); for (int x = 0; x < width; x++) { for (int y = 0; y < height; y++) { var _emissive = emissiveBitmap != null ? emissiveBitmap.GetPixel(x, y).toArrayRGB().Multiply(1f / 255.0f) : defaultEmissive; var _diffuse = diffuseBitmap != null ? diffuseBitmap.GetPixel(x, y).toArrayRGB().Multiply(1f / 255.0f) : defaultDiffuse; var emissivePremultiplied = _emissive.Multiply(_diffuse); Color colorEmissivePremultiplied = Color.FromArgb( (int)(emissivePremultiplied[0] * 255), (int)(emissivePremultiplied[1] * 255), (int)(emissivePremultiplied[2] * 255) ); emissivePremultipliedBitmap.SetPixel(x, y, colorEmissivePremultiplied); } } } } var name = babylonMaterial.name + "_emissive.jpg"; return ExportBitmapTexture(gltf, babylonTexture, emissivePremultipliedBitmap, name); }
private void ExportMaterial(IIGameMaterial materialNode, BabylonScene babylonScene) { var name = materialNode.MaterialName; var id = materialNode.MaxMaterial.GetGuid().ToString(); RaiseMessage(name, 1); // --- prints --- { RaiseMessage("materialNode.MaterialClass=" + materialNode.MaterialClass, 2); RaiseMessage("materialNode.NumberOfTextureMaps=" + materialNode.NumberOfTextureMaps, 2); var propertyContainer = materialNode.IPropertyContainer; RaiseMessage("propertyContainer=" + propertyContainer, 2); if (propertyContainer != null) { RaiseMessage("propertyContainer.NumberOfProperties=" + propertyContainer.NumberOfProperties, 3); for (int i = 0; i < propertyContainer.NumberOfProperties; i++) { var prop = propertyContainer.GetProperty(i); if (prop != null) { RaiseMessage("propertyContainer.GetProperty(" + i + ")=" + prop.Name, 3); switch (prop.GetType_) { case PropType.StringProp: string propertyString = ""; RaiseMessage("prop.GetPropertyValue(ref propertyString, 0)=" + prop.GetPropertyValue(ref propertyString, 0), 4); RaiseMessage("propertyString=" + propertyString, 4); break; case PropType.IntProp: int propertyInt = 0; RaiseMessage("prop.GetPropertyValue(ref propertyInt, 0)=" + prop.GetPropertyValue(ref propertyInt, 0), 4); RaiseMessage("propertyInt=" + propertyInt, 4); break; case PropType.FloatProp: float propertyFloat = 0; RaiseMessage("prop.GetPropertyValue(ref propertyFloat, 0)=" + prop.GetPropertyValue(ref propertyFloat, 0, true), 4); RaiseMessage("propertyFloat=" + propertyFloat, 4); RaiseMessage("prop.GetPropertyValue(ref propertyFloat, 0)=" + prop.GetPropertyValue(ref propertyFloat, 0, false), 4); RaiseMessage("propertyFloat=" + propertyFloat, 4); break; case PropType.Point3Prop: IPoint3 propertyPoint3 = Loader.Global.Point3.Create(0, 0, 0); RaiseMessage("prop.GetPropertyValue(ref propertyPoint3, 0)=" + prop.GetPropertyValue(propertyPoint3, 0), 4); RaiseMessage("propertyPoint3=" + Point3ToString(propertyPoint3), 4); break; case PropType.Point4Prop: IPoint4 propertyPoint4 = Loader.Global.Point4.Create(0, 0, 0, 0); RaiseMessage("prop.GetPropertyValue(ref propertyPoint4, 0)=" + prop.GetPropertyValue(propertyPoint4, 0), 4); RaiseMessage("propertyPoint4=" + Point4ToString(propertyPoint4), 4); break; case PropType.UnknownProp: default: RaiseMessage("Unknown property type", 4); break; } } else { RaiseMessage("propertyContainer.GetProperty(" + i + ") IS NULL", 3); } } } } if (materialNode.SubMaterialCount > 0) { var babylonMultimaterial = new BabylonMultiMaterial { name = name, id = id }; var guids = new List <string>(); for (var index = 0; index < materialNode.SubMaterialCount; index++) { var subMat = materialNode.GetSubMaterial(index); if (subMat != null) { guids.Add(subMat.MaxMaterial.GetGuid().ToString()); if (!referencedMaterials.Contains(subMat)) { referencedMaterials.Add(subMat); ExportMaterial(subMat, babylonScene); } } else { guids.Add(Guid.Empty.ToString()); } } babylonMultimaterial.materials = guids.ToArray(); babylonScene.MultiMaterialsList.Add(babylonMultimaterial); return; } var stdMat = materialNode.MaxMaterial.GetParamBlock(0).Owner as IStdMat2; if (stdMat != null) { var babylonMaterial = new BabylonStandardMaterial { name = name, id = id, ambient = materialNode.MaxMaterial.GetAmbient(0, false).ToArray(), diffuse = materialNode.MaxMaterial.GetDiffuse(0, false).ToArray(), specular = materialNode.MaxMaterial.GetSpecular(0, false).Scale(materialNode.MaxMaterial.GetShinStr(0, false)), specularPower = materialNode.MaxMaterial.GetShininess(0, false) * 256, emissive = materialNode.MaxMaterial.GetSelfIllumColorOn(0, false) ? materialNode.MaxMaterial.GetSelfIllumColor(0, false).ToArray() : materialNode.MaxMaterial.GetDiffuse(0, false).Scale(materialNode.MaxMaterial.GetSelfIllum(0, false)), alpha = 1.0f - materialNode.MaxMaterial.GetXParency(0, false) }; babylonMaterial.backFaceCulling = !stdMat.TwoSided; babylonMaterial.wireframe = stdMat.Wire; // Textures BabylonFresnelParameters fresnelParameters; babylonMaterial.ambientTexture = ExportTexture(stdMat, 0, out fresnelParameters, babylonScene); // Ambient babylonMaterial.diffuseTexture = ExportTexture(stdMat, 1, out fresnelParameters, babylonScene); // Diffuse if (fresnelParameters != null) { babylonMaterial.diffuseFresnelParameters = fresnelParameters; } babylonMaterial.specularTexture = ExportTexture(stdMat, 2, out fresnelParameters, babylonScene); // Specular babylonMaterial.emissiveTexture = ExportTexture(stdMat, 5, out fresnelParameters, babylonScene); // Emissive if (fresnelParameters != null) { babylonMaterial.emissiveFresnelParameters = fresnelParameters; if (babylonMaterial.emissive[0] == 0 && babylonMaterial.emissive[1] == 0 && babylonMaterial.emissive[2] == 0 && babylonMaterial.emissiveTexture == null) { babylonMaterial.emissive = new float[] { 1, 1, 1 }; } } babylonMaterial.opacityTexture = ExportTexture(stdMat, 6, out fresnelParameters, babylonScene, false, true); // Opacity if (fresnelParameters != null) { babylonMaterial.opacityFresnelParameters = fresnelParameters; if (babylonMaterial.alpha == 1 && babylonMaterial.opacityTexture == null) { babylonMaterial.alpha = 0; } } babylonMaterial.bumpTexture = ExportTexture(stdMat, 8, out fresnelParameters, babylonScene); // Bump babylonMaterial.reflectionTexture = ExportTexture(stdMat, 9, out fresnelParameters, babylonScene, true); // Reflection if (fresnelParameters != null) { if (babylonMaterial.reflectionTexture == null) { RaiseWarning("Fallout cannot be used with reflection channel without a texture", 2); } else { babylonMaterial.reflectionFresnelParameters = fresnelParameters; } } // Constraints if (babylonMaterial.diffuseTexture != null) { babylonMaterial.diffuse = new[] { 1.0f, 1.0f, 1.0f }; } if (babylonMaterial.emissiveTexture != null) { babylonMaterial.emissive = new float[] { 0, 0, 0 }; } if (babylonMaterial.opacityTexture != null && babylonMaterial.diffuseTexture != null && babylonMaterial.diffuseTexture.name == babylonMaterial.opacityTexture.name && babylonMaterial.diffuseTexture.hasAlpha && !babylonMaterial.opacityTexture.getAlphaFromRGB) { // This is a alpha testing purpose babylonMaterial.opacityTexture = null; babylonMaterial.diffuseTexture.hasAlpha = true; RaiseWarning("Opacity texture was removed because alpha from diffuse texture can be use instead", 2); RaiseWarning("If you do not want this behavior, just set Alpha Source = None on your diffuse texture", 2); } babylonScene.MaterialsList.Add(babylonMaterial); } else if (materialNode.MaterialClass == "Physical Material") { var propertyContainer = materialNode.IPropertyContainer; var babylonMaterial = new BabylonPBRMetallicRoughnessMaterial { name = name, id = id }; // --- Global --- // Alpha // --- // TODO - Unclear if alpha must be stored within 'alpha' property of BABYLON.Material // or within alpha channel of 'baseColor' of BABYLON.PBRMetallicRoughnessMaterial // --- // TODO - XParency seems computed from several parameters // 'Transparency' property is one of them // Which value to use? var alphaFromXParency = 1.0f - materialNode.MaxMaterial.GetXParency(0, false); var alphaFromPropertyContainer = 1.0f - propertyContainer.GetFloatProperty(17); RaiseMessage("alphaFromXParency=" + alphaFromXParency, 2); RaiseMessage("alphaFromPropertyContainer=" + alphaFromPropertyContainer, 2); babylonMaterial.alpha = alphaFromXParency; babylonMaterial.baseColor = materialNode.MaxMaterial.GetDiffuse(0, false).ToArray(); babylonMaterial.metallic = propertyContainer.GetFloatProperty(6); babylonMaterial.roughness = propertyContainer.GetFloatProperty(4); if (propertyContainer.GetIntProperty(5) == 1) { // Inverse roughness babylonMaterial.roughness = 1 - babylonMaterial.roughness; } // Self illumination is computed from emission color, luminance, temperature and weight babylonMaterial.emissiveColor = materialNode.MaxMaterial.GetSelfIllumColorOn(0, false) ? materialNode.MaxMaterial.GetSelfIllumColor(0, false).ToArray() : materialNode.MaxMaterial.GetDiffuse(0, false).Scale(materialNode.MaxMaterial.GetSelfIllum(0, false)); // --- Textures --- babylonMaterial.baseTexture = ExportBaseColorAlphaTexture(materialNode, babylonScene, name); if (babylonMaterial.alpha != 1.0f || (babylonMaterial.baseTexture != null && babylonMaterial.baseTexture.hasAlpha)) { babylonMaterial.transparencyMode = (int)BabylonPBRMetallicRoughnessMaterial.TransparencyMode.ALPHABLEND; } babylonMaterial.metallicRoughnessTexture = ExportMetallicRoughnessTexture(materialNode, babylonMaterial.metallic, babylonMaterial.roughness, babylonScene, name); babylonMaterial.environmentTexture = ExportPBRTexture(materialNode, 3, babylonScene); var normalMapAmount = propertyContainer.GetFloatProperty(91); babylonMaterial.normalTexture = ExportPBRTexture(materialNode, 30, babylonScene, normalMapAmount); babylonMaterial.emissiveTexture = ExportPBRTexture(materialNode, 17, babylonScene); // Constraints if (babylonMaterial.baseTexture != null) { babylonMaterial.baseColor = new[] { 1.0f, 1.0f, 1.0f }; } if (babylonMaterial.emissiveTexture != null) { babylonMaterial.emissiveColor = new float[] { 0, 0, 0 }; } babylonScene.MaterialsList.Add(babylonMaterial); } else { RaiseWarning("Unsupported material type: " + materialNode.MaterialClass, 2); } }
private void ExportMaterial(MFnDependencyNode materialDependencyNode, BabylonScene babylonScene, bool fullPBR) { MObject materialObject = materialDependencyNode.objectProperty; var name = materialDependencyNode.name; var id = materialDependencyNode.uuid().asString(); RaiseMessage(name, 1); RaiseMessage(materialObject.apiType.ToString(), 1); RaiseVerbose("materialObject.hasFn(MFn.Type.kBlinn)=" + materialObject.hasFn(MFn.Type.kBlinn), 2); RaiseVerbose("materialObject.hasFn(MFn.Type.kPhong)=" + materialObject.hasFn(MFn.Type.kPhong), 2); RaiseVerbose("materialObject.hasFn(MFn.Type.kPhongExplorer)=" + materialObject.hasFn(MFn.Type.kPhongExplorer), 2); Print(materialDependencyNode, 2, "Print ExportMaterial materialDependencyNode"); // Retreive Babylon Material dependency node MFnDependencyNode babylonAttributesDependencyNode = getBabylonMaterialNode(materialDependencyNode); // Standard material if (materialObject.hasFn(MFn.Type.kLambert)) { if (materialObject.hasFn(MFn.Type.kBlinn)) { RaiseMessage("Blinn shader", 2); } else if (materialObject.hasFn(MFn.Type.kPhong)) { RaiseMessage("Phong shader", 2); } else if (materialObject.hasFn(MFn.Type.kPhongExplorer)) { RaiseMessage("Phong E shader", 2); } else { RaiseMessage("Lambert shader", 2); } var lambertShader = new MFnLambertShader(materialObject); RaiseVerbose("typeId=" + lambertShader.typeId, 2); RaiseVerbose("typeName=" + lambertShader.typeName, 2); RaiseVerbose("color=" + lambertShader.color.toString(), 2); RaiseVerbose("transparency=" + lambertShader.transparency.toString(), 2); RaiseVerbose("ambientColor=" + lambertShader.ambientColor.toString(), 2); RaiseVerbose("incandescence=" + lambertShader.incandescence.toString(), 2); RaiseVerbose("diffuseCoeff=" + lambertShader.diffuseCoeff, 2); RaiseVerbose("translucenceCoeff=" + lambertShader.translucenceCoeff, 2); BabylonStandardMaterial babylonMaterial = new BabylonStandardMaterial(id) { name = name, diffuse = lambertShader.color.toArrayRGB() }; // User custom attributes babylonMaterial.metadata = ExportCustomAttributeFromMaterial(babylonMaterial); bool isTransparencyModeFromBabylonMaterialNode = false; if (babylonAttributesDependencyNode != null) { // Transparency mode if (babylonAttributesDependencyNode.hasAttribute("babylonTransparencyMode")) { int transparencyMode = babylonAttributesDependencyNode.findPlug("babylonTransparencyMode").asInt(); babylonMaterial.transparencyMode = transparencyMode; isTransparencyModeFromBabylonMaterialNode = true; } } // Maya ambient <=> babylon emissive babylonMaterial.emissive = lambertShader.ambientColor.toArrayRGB(); babylonMaterial.linkEmissiveWithDiffuse = true; // Incandescence (or Illumination) is not exported if (isTransparencyModeFromBabylonMaterialNode == false || babylonMaterial.transparencyMode != 0) { // If transparency is not a shade of grey (shade of grey <=> R=G=B) if (lambertShader.transparency[0] != lambertShader.transparency[1] || lambertShader.transparency[0] != lambertShader.transparency[2]) { RaiseWarning("Transparency color is not a shade of grey. Only it's R channel is used.", 2); } // Convert transparency to opacity babylonMaterial.alpha = 1.0f - lambertShader.transparency[0]; } // Specular power if (materialObject.hasFn(MFn.Type.kReflect)) { var reflectShader = new MFnReflectShader(materialObject); RaiseVerbose("specularColor=" + reflectShader.specularColor.toString(), 2); RaiseVerbose("reflectivity=" + reflectShader.reflectivity, 2); RaiseVerbose("reflectedColor=" + reflectShader.reflectedColor.toString(), 2); babylonMaterial.specular = reflectShader.specularColor.toArrayRGB(); if (materialObject.hasFn(MFn.Type.kBlinn)) { MFnBlinnShader blinnShader = new MFnBlinnShader(materialObject); babylonMaterial.specularPower = (1.0f - blinnShader.eccentricity) * 256; } else if (materialObject.hasFn(MFn.Type.kPhong)) { MFnPhongShader phongShader = new MFnPhongShader(materialObject); float glossiness = (float)Math.Log(phongShader.cosPower, 2) * 10; babylonMaterial.specularPower = glossiness / 100 * 256; } else if (materialObject.hasFn(MFn.Type.kPhongExplorer)) { MFnPhongEShader phongEShader = new MFnPhongEShader(materialObject); // No use of phongE.whiteness and phongE.highlightSize babylonMaterial.specularPower = (1.0f - phongEShader.roughness) * 256; } else { RaiseWarning("Unknown reflect shader type: " + reflectShader.typeName + ". Specular power is default 64. Consider using a Blinn or Phong shader instead.", 2); } } // TODO //babylonMaterial.wireframe = stdMat.Wire; // --- Textures --- babylonMaterial.diffuseTexture = ExportTexture(materialDependencyNode, "color", babylonScene); babylonMaterial.emissiveTexture = ExportTexture(materialDependencyNode, "ambientColor", babylonScene); // Maya ambient <=> babylon emissive babylonMaterial.bumpTexture = ExportTexture(materialDependencyNode, "normalCamera", babylonScene); if (isTransparencyModeFromBabylonMaterialNode == false || babylonMaterial.transparencyMode != 0) { babylonMaterial.opacityTexture = ExportTexture(materialDependencyNode, "transparency", babylonScene, false, true); } if (materialObject.hasFn(MFn.Type.kReflect)) { babylonMaterial.specularTexture = ExportTexture(materialDependencyNode, "specularColor", babylonScene); babylonMaterial.reflectionTexture = ExportTexture(materialDependencyNode, "reflectedColor", babylonScene, true, false, true); } if (isTransparencyModeFromBabylonMaterialNode == false && (babylonMaterial.alpha != 1.0f || (babylonMaterial.diffuseTexture != null && babylonMaterial.diffuseTexture.hasAlpha) || babylonMaterial.opacityTexture != null)) { babylonMaterial.transparencyMode = (int)BabylonPBRMetallicRoughnessMaterial.TransparencyMode.ALPHABLEND; } // Constraints if (babylonMaterial.diffuseTexture != null) { babylonMaterial.diffuse = new[] { 1.0f, 1.0f, 1.0f }; } if (babylonMaterial.emissiveTexture != null) { babylonMaterial.emissive = new float[] { 0, 0, 0 }; } if (babylonMaterial.transparencyMode == (int)BabylonPBRMetallicRoughnessMaterial.TransparencyMode.ALPHATEST) { // Set the alphaCutOff value explicitely to avoid different interpretations on different engines // Use the glTF default value rather than the babylon one babylonMaterial.alphaCutOff = 0.5f; } if (babylonAttributesDependencyNode == null) { // Create Babylon Material dependency node babylonStandardMaterialNode.Create(materialDependencyNode); // Retreive Babylon Material dependency node babylonAttributesDependencyNode = getBabylonMaterialNode(materialDependencyNode); } if (babylonAttributesDependencyNode != null) { // Ensure all attributes are setup babylonStandardMaterialNode.Init(babylonAttributesDependencyNode, babylonMaterial); RaiseVerbose("Babylon Attributes of " + babylonAttributesDependencyNode.name, 2); // Common attributes ExportCommonBabylonAttributes(babylonAttributesDependencyNode, babylonMaterial); // Special treatment for Unlit if (babylonMaterial.isUnlit) { if ((babylonMaterial.emissive != null && (babylonMaterial.emissive[0] != 0 || babylonMaterial.emissive[1] != 0 || babylonMaterial.emissive[2] != 0)) || (babylonMaterial.emissiveTexture != null) || (babylonMaterial.emissiveFresnelParameters != null)) { RaiseWarning("Material is unlit. Emission is discarded and replaced by diffuse.", 2); } // Copy diffuse to emissive babylonMaterial.emissive = babylonMaterial.diffuse; babylonMaterial.emissiveTexture = babylonMaterial.diffuseTexture; babylonMaterial.emissiveFresnelParameters = babylonMaterial.diffuseFresnelParameters; babylonMaterial.disableLighting = true; babylonMaterial.linkEmissiveWithDiffuse = false; } // Special treatment for "Alpha test" transparency mode if (babylonMaterial.transparencyMode == (int)BabylonPBRMetallicRoughnessMaterial.TransparencyMode.ALPHATEST && ((babylonMaterial.diffuseTexture != null && babylonMaterial.opacityTexture != null && babylonMaterial.diffuseTexture.originalPath != babylonMaterial.opacityTexture.originalPath) || (babylonMaterial.diffuseTexture == null && babylonMaterial.opacityTexture != null))) { // Base color and alpha files need to be merged into a single file Color defaultColor = Color.FromArgb((int)(babylonMaterial.diffuse[0] * 255), (int)(babylonMaterial.diffuse[1] * 255), (int)(babylonMaterial.diffuse[2] * 255)); MFnDependencyNode baseColorTextureDependencyNode = getTextureDependencyNode(materialDependencyNode, "color"); MFnDependencyNode opacityTextureDependencyNode = getTextureDependencyNode(materialDependencyNode, "transparency"); babylonMaterial.diffuseTexture = ExportBaseColorAlphaTexture(baseColorTextureDependencyNode, opacityTextureDependencyNode, babylonScene, name, defaultColor, babylonMaterial.alpha); babylonMaterial.opacityTexture = null; babylonMaterial.alpha = 1.0f; } } babylonScene.MaterialsList.Add(babylonMaterial); } // Stingray PBS material else if (isStingrayPBSMaterial(materialDependencyNode)) { RaiseMessage("Stingray shader", 2); var babylonMaterial = new BabylonPBRMetallicRoughnessMaterial(id) { name = name }; // --- Global --- // Color3 babylonMaterial.baseColor = materialDependencyNode.findPlug("base_color").asFloatArray(); // Alpha string opacityAttributeName = "opacity"; if (materialDependencyNode.hasAttribute(opacityAttributeName)) { float opacityAttributeValue = materialDependencyNode.findPlug(opacityAttributeName).asFloat(); babylonMaterial.alpha = 1.0f - opacityAttributeValue; } // Metallic & roughness babylonMaterial.metallic = materialDependencyNode.findPlug("metallic").asFloat(); babylonMaterial.roughness = materialDependencyNode.findPlug("roughness").asFloat(); // Emissive float emissiveIntensity = materialDependencyNode.findPlug("emissive_intensity").asFloat(); // Factor emissive color with emissive intensity emissiveIntensity = Tools.Clamp(emissiveIntensity, 0f, 1f); babylonMaterial.emissive = materialDependencyNode.findPlug("emissive").asFloatArray().Multiply(emissiveIntensity); // --- Textures --- // Base color & alpha bool useColorMap = materialDependencyNode.findPlug("use_color_map").asBool(); bool useOpacityMap = false; string useOpacityMapAttributeName = "use_opacity_map"; if (materialDependencyNode.hasAttribute(useOpacityMapAttributeName)) { useOpacityMap = materialDependencyNode.findPlug(useOpacityMapAttributeName).asBool(); } if (materialDependencyNode.hasAttribute("mask_threshold")) // Preset "Masked" { if (useColorMap && useOpacityMap) { // Texture is assumed to be already merged babylonMaterial.baseTexture = ExportTexture(materialDependencyNode, "TEX_color_map", babylonScene, false, true); } else if (useColorMap || useOpacityMap) { // Merge Diffuse and Mask Color defaultColor = Color.FromArgb((int)(babylonMaterial.baseColor[0] * 255), (int)(babylonMaterial.baseColor[1] * 255), (int)(babylonMaterial.baseColor[2] * 255)); // In Maya, a Masked StingrayPBS material without opacity or mask textures is counted as being fully transparent // Such material is visible only when the mask threshold is set to 0 float defaultOpacity = 0; // Either use the color map MFnDependencyNode baseColorTextureDependencyNode = null; if (useColorMap) { baseColorTextureDependencyNode = getTextureDependencyNode(materialDependencyNode, "TEX_color_map"); } // Or the opacity map MFnDependencyNode opacityTextureDependencyNode = null; if (useOpacityMap) { opacityTextureDependencyNode = getTextureDependencyNode(materialDependencyNode, "TEX_color_map"); } // Merge default value and texture babylonMaterial.baseTexture = ExportBaseColorAlphaTexture(baseColorTextureDependencyNode, opacityTextureDependencyNode, babylonScene, babylonMaterial.name, defaultColor, defaultOpacity); } else { // In Maya, a Masked StingrayPBS material without opacity or mask textures is counted as being fully transparent // Such material is visible only when the mask threshold is set to 0 babylonMaterial.alpha = 0; } } else { if (useColorMap || useOpacityMap) { // Force non use map to default value // Ex: if useOpacityMap == false, force alpha = 255 for all pixels. babylonMaterial.baseTexture = ExportTexture(materialDependencyNode, "TEX_color_map", babylonScene, false, useOpacityMap); } } if (babylonMaterial.transparencyMode == (int)BabylonPBRMetallicRoughnessMaterial.TransparencyMode.ALPHATEST) { // Set the alphaCutOff value explicitely to avoid different interpretations on different engines // Use the glTF default value rather than the babylon one babylonMaterial.alphaCutOff = 0.5f; } // Alpha cuttoff if (materialDependencyNode.hasAttribute("mask_threshold")) // Preset "Masked" { babylonMaterial.alphaCutOff = materialDependencyNode.findPlug("mask_threshold").asFloat(); } // Metallic, roughness, ambient occlusion bool useMetallicMap = materialDependencyNode.findPlug("use_metallic_map").asBool(); bool useRoughnessMap = materialDependencyNode.findPlug("use_roughness_map").asBool(); string useAOMapAttributeName = "use_ao_map"; bool useAOMap = materialDependencyNode.hasAttribute(useAOMapAttributeName) && materialDependencyNode.findPlug(useAOMapAttributeName).asBool(); MFnDependencyNode metallicTextureDependencyNode = useMetallicMap ? getTextureDependencyNode(materialDependencyNode, "TEX_metallic_map") : null; MFnDependencyNode roughnessTextureDependencyNode = useRoughnessMap ? getTextureDependencyNode(materialDependencyNode, "TEX_roughness_map") : null; MFnDependencyNode ambientOcclusionTextureDependencyNode = useAOMap ? getTextureDependencyNode(materialDependencyNode, "TEX_ao_map") : null; // Check if MR or ORM textures are already merged bool areTexturesAlreadyMerged = false; if (metallicTextureDependencyNode != null && roughnessTextureDependencyNode != null) { string sourcePathMetallic = getSourcePathFromFileTexture(metallicTextureDependencyNode); string sourcePathRoughness = getSourcePathFromFileTexture(roughnessTextureDependencyNode); if (sourcePathMetallic == sourcePathRoughness) { if (ambientOcclusionTextureDependencyNode != null) { string sourcePathAmbientOcclusion = getSourcePathFromFileTexture(ambientOcclusionTextureDependencyNode); if (sourcePathMetallic == sourcePathAmbientOcclusion) { // Metallic, roughness and ambient occlusion are already merged RaiseVerbose("Metallic, roughness and ambient occlusion are already merged", 2); BabylonTexture ormTexture = ExportTexture(metallicTextureDependencyNode, babylonScene); babylonMaterial.metallicRoughnessTexture = ormTexture; babylonMaterial.occlusionTexture = ormTexture; areTexturesAlreadyMerged = true; } } else { // Metallic and roughness are already merged RaiseVerbose("Metallic and roughness are already merged", 2); BabylonTexture ormTexture = ExportTexture(metallicTextureDependencyNode, babylonScene); babylonMaterial.metallicRoughnessTexture = ormTexture; areTexturesAlreadyMerged = true; } } } if (areTexturesAlreadyMerged == false) { if (metallicTextureDependencyNode != null || roughnessTextureDependencyNode != null) { // Merge metallic, roughness and ambient occlusion RaiseVerbose("Merge metallic, roughness and ambient occlusion", 2); BabylonTexture ormTexture = ExportORMTexture(babylonScene, metallicTextureDependencyNode, roughnessTextureDependencyNode, ambientOcclusionTextureDependencyNode, babylonMaterial.metallic, babylonMaterial.roughness); babylonMaterial.metallicRoughnessTexture = ormTexture; if (ambientOcclusionTextureDependencyNode != null) { babylonMaterial.occlusionTexture = ormTexture; } } else if (ambientOcclusionTextureDependencyNode != null) { // Simply export occlusion texture RaiseVerbose("Simply export occlusion texture", 2); babylonMaterial.occlusionTexture = ExportTexture(ambientOcclusionTextureDependencyNode, babylonScene); } } // Normal if (materialDependencyNode.findPlug("use_normal_map").asBool()) { babylonMaterial.normalTexture = ExportTexture(materialDependencyNode, "TEX_normal_map", babylonScene); } // Emissive bool useEmissiveMap = materialDependencyNode.findPlug("use_emissive_map").asBool(); if (useEmissiveMap) { babylonMaterial.emissiveTexture = ExportTexture(materialDependencyNode, "TEX_emissive_map", babylonScene, false, false, false, emissiveIntensity); } // Constraints if (useColorMap) { babylonMaterial.baseColor = new[] { 1.0f, 1.0f, 1.0f }; } if (useOpacityMap) { babylonMaterial.alpha = 1.0f; } if (babylonMaterial.alpha != 1.0f || (babylonMaterial.baseTexture != null && babylonMaterial.baseTexture.hasAlpha)) { if (materialDependencyNode.hasAttribute("mask_threshold")) { babylonMaterial.transparencyMode = (int)BabylonPBRMetallicRoughnessMaterial.TransparencyMode.ALPHATEST; } else { babylonMaterial.transparencyMode = (int)BabylonPBRMetallicRoughnessMaterial.TransparencyMode.ALPHABLEND; } } if (useMetallicMap) { babylonMaterial.metallic = 1.0f; } if (useRoughnessMap) { babylonMaterial.roughness = 1.0f; } if (useEmissiveMap) { babylonMaterial.emissive = new[] { 1.0f, 1.0f, 1.0f }; } // User custom attributes babylonMaterial.metadata = ExportCustomAttributeFromMaterial(babylonMaterial); if (babylonAttributesDependencyNode == null) { // Create Babylon Material dependency node babylonStingrayPBSMaterialNode.Create(materialDependencyNode); // Retreive Babylon Material dependency node babylonAttributesDependencyNode = getBabylonMaterialNode(materialDependencyNode); } if (babylonAttributesDependencyNode != null) { // Ensure all attributes are setup babylonStingrayPBSMaterialNode.Init(babylonAttributesDependencyNode, babylonMaterial); RaiseVerbose("Babylon Attributes of " + babylonAttributesDependencyNode.name, 2); // Common attributes ExportCommonBabylonAttributes(babylonAttributesDependencyNode, babylonMaterial); babylonMaterial.doubleSided = !babylonMaterial.backFaceCulling; babylonMaterial._unlit = babylonMaterial.isUnlit; // Update displayed Transparency mode value based on StingrayPBS preset material MGlobal.executeCommand($"setAttr - l false {{ \"{babylonAttributesDependencyNode.name}.babylonTransparencyMode\" }}"); // Unlock attribute int babylonTransparencyMode = 0; if (materialDependencyNode.hasAttribute("mask_threshold")) { babylonTransparencyMode = 1; } else if (materialDependencyNode.hasAttribute("use_opacity_map")) { babylonTransparencyMode = 2; } MGlobal.executeCommand($"setAttr \"{babylonAttributesDependencyNode.name}.babylonTransparencyMode\" {babylonTransparencyMode};"); MGlobal.executeCommand($"setAttr - l true {{ \"{babylonAttributesDependencyNode.name}.babylonTransparencyMode\" }}"); // Lock it afterwards } babylonScene.MaterialsList.Add(babylonMaterial); } // Arnold Ai Standard Surface else if (isAiStandardSurface(materialDependencyNode)) { RaiseMessage("Ai Standard Surface shader", 2); var babylonMaterial = new BabylonPBRMetallicRoughnessMaterial(id) { name = name }; // User custom attributes babylonMaterial.metadata = ExportCustomAttributeFromMaterial(babylonMaterial); // --- Global --- bool isTransparencyModeFromBabylonMaterialNode = false; if (babylonAttributesDependencyNode != null) { // Transparency mode if (babylonAttributesDependencyNode.hasAttribute("babylonTransparencyMode")) { babylonMaterial.transparencyMode = babylonAttributesDependencyNode.findPlug("babylonTransparencyMode").asInt(); isTransparencyModeFromBabylonMaterialNode = true; } } // Color3 float baseWeight = materialDependencyNode.findPlug("base").asFloat(); float[] baseColor = materialDependencyNode.findPlug("baseColor").asFloatArray(); babylonMaterial.baseColor = baseColor.Multiply(baseWeight); // Alpha MaterialDuplicationData materialDuplicationData = materialDuplicationDatas[id]; // If at least one mesh is Transparent and is using this material either directly or as a sub material if ((isTransparencyModeFromBabylonMaterialNode == false || babylonMaterial.transparencyMode != 0) && materialDuplicationData.isArnoldTransparent()) { float[] opacityAttributeValue = materialDependencyNode.findPlug("opacity").asFloatArray(); babylonMaterial.alpha = opacityAttributeValue[0]; } else { // Do not bother about alpha babylonMaterial.alpha = 1.0f; } // Metallic & roughness babylonMaterial.metallic = materialDependencyNode.findPlug("metalness").asFloat(); babylonMaterial.roughness = materialDependencyNode.findPlug("specularRoughness").asFloat(); // Emissive float emissionWeight = materialDependencyNode.findPlug("emission").asFloat(); babylonMaterial.emissive = materialDependencyNode.findPlug("emissionColor").asFloatArray().Multiply(emissionWeight); var list = new List <string>(); for (int i = 0; i < materialDependencyNode.attributeCount; i++) { var attr = materialDependencyNode.attribute((uint)i); var plug = materialDependencyNode.findPlug(attr); //string aliasName; //materialDependencyNode.getPlugsAlias(plug, out aliasName); System.Diagnostics.Debug.WriteLine(plug.name + i.ToString()); } // --- Clear Coat --- float coatWeight = materialDependencyNode.findPlug("coat").asFloat(); MFnDependencyNode intensityCoatTextureDependencyNode = getTextureDependencyNode(materialDependencyNode, "coat"); if (coatWeight > 0.0f || intensityCoatTextureDependencyNode != null) { babylonMaterial.clearCoat.isEnabled = true; babylonMaterial.clearCoat.indexOfRefraction = materialDependencyNode.findPlug("coatIOR").asFloat(); var coatRoughness = materialDependencyNode.findPlug("coatRoughness").asFloat(); MFnDependencyNode roughnessCoatTextureDependencyNode = getTextureDependencyNode(materialDependencyNode, "coatRoughness"); var coatTexture = ExportCoatTexture(intensityCoatTextureDependencyNode, roughnessCoatTextureDependencyNode, babylonScene, name, coatWeight, coatRoughness); if (coatTexture != null) { babylonMaterial.clearCoat.texture = coatTexture; babylonMaterial.clearCoat.roughness = 1.0f; babylonMaterial.clearCoat.intensity = 1.0f; } else { babylonMaterial.clearCoat.intensity = coatWeight; babylonMaterial.clearCoat.roughness = coatRoughness; } float[] coatColor = materialDependencyNode.findPlug("coatColor").asFloatArray(); if (coatColor[0] != 1.0f || coatColor[1] != 1.0f || coatColor[2] != 1.0f) { babylonMaterial.clearCoat.isTintEnabled = true; babylonMaterial.clearCoat.tintColor = coatColor; } babylonMaterial.clearCoat.tintTexture = ExportTexture(materialDependencyNode, "coatColor", babylonScene); if (babylonMaterial.clearCoat.tintTexture != null) { babylonMaterial.clearCoat.tintColor = new[] { 1.0f, 1.0f, 1.0f }; babylonMaterial.clearCoat.isTintEnabled = true; } // EyeBall deduction... babylonMaterial.clearCoat.tintThickness = 0.65f; babylonMaterial.clearCoat.bumpTexture = ExportTexture(materialDependencyNode, "coatNormal", babylonScene); } // --- Textures --- // Base color & alpha if ((isTransparencyModeFromBabylonMaterialNode == false || babylonMaterial.transparencyMode != 0) && materialDuplicationData.isArnoldTransparent()) { MFnDependencyNode baseColorTextureDependencyNode = getTextureDependencyNode(materialDependencyNode, "baseColor"); MFnDependencyNode opacityTextureDependencyNode = getTextureDependencyNode(materialDependencyNode, "opacity"); if (baseColorTextureDependencyNode != null && opacityTextureDependencyNode != null && getSourcePathFromFileTexture(baseColorTextureDependencyNode) == getSourcePathFromFileTexture(opacityTextureDependencyNode)) { // If the same file is used for base color and opacity // Base color and alpha are already merged into a single file babylonMaterial.baseTexture = ExportTexture(baseColorTextureDependencyNode, babylonScene, false, true); } else { // Base color and alpha files need to be merged into a single file Color _baseColor = Color.FromArgb((int)(baseColor[0] * 255), (int)(baseColor[1] * 255), (int)(baseColor[2] * 255)); babylonMaterial.baseTexture = ExportBaseColorAlphaTexture(baseColorTextureDependencyNode, opacityTextureDependencyNode, babylonScene, name, _baseColor, babylonMaterial.alpha); } } else { // Base color only // Do not bother about alpha babylonMaterial.baseTexture = ExportTexture(materialDependencyNode, "baseColor", babylonScene); } // Metallic & roughness MFnDependencyNode metallicTextureDependencyNode = getTextureDependencyNode(materialDependencyNode, "metalness"); MFnDependencyNode roughnessTextureDependencyNode = getTextureDependencyNode(materialDependencyNode, "specularRoughness"); if (metallicTextureDependencyNode != null && roughnessTextureDependencyNode != null && getSourcePathFromFileTexture(metallicTextureDependencyNode) == getSourcePathFromFileTexture(roughnessTextureDependencyNode)) { // If the same file is used for metallic and roughness // Then we assume it's an ORM file (Red=Occlusion, Green=Roughness, Blue=Metallic) // Metallic and roughness are already merged into a single file babylonMaterial.metallicRoughnessTexture = ExportTexture(metallicTextureDependencyNode, babylonScene); // Use same file for Ambient occlusion babylonMaterial.occlusionTexture = babylonMaterial.metallicRoughnessTexture; } else { // Metallic and roughness files need to be merged into a single file // Occlusion texture is not exported since aiStandardSurface material doesn't provide input for it babylonMaterial.metallicRoughnessTexture = ExportORMTexture(babylonScene, metallicTextureDependencyNode, roughnessTextureDependencyNode, null, babylonMaterial.metallic, babylonMaterial.roughness); } // Normal babylonMaterial.normalTexture = ExportTexture(materialDependencyNode, "normalCamera", babylonScene); // Emissive babylonMaterial.emissiveTexture = ExportTexture(materialDependencyNode, "emissionColor", babylonScene); // Constraints if (babylonMaterial.baseTexture != null) { babylonMaterial.baseColor = new[] { baseWeight, baseWeight, baseWeight }; babylonMaterial.alpha = 1.0f; } if (babylonMaterial.metallicRoughnessTexture != null) { babylonMaterial.metallic = 1.0f; babylonMaterial.roughness = 1.0f; } if (babylonMaterial.emissiveTexture != null) { babylonMaterial.emissive = new[] { emissionWeight, emissionWeight, emissionWeight }; } // If this material is containing alpha data if (babylonMaterial.alpha != 1.0f || (babylonMaterial.baseTexture != null && babylonMaterial.baseTexture.hasAlpha)) { if (isTransparencyModeFromBabylonMaterialNode == false) { babylonMaterial.transparencyMode = (int)BabylonPBRMetallicRoughnessMaterial.TransparencyMode.ALPHABLEND; } // If this material is assigned to both Transparent and Opaque meshes (either directly or as a sub material) if (materialDuplicationData.isDuplicationRequired()) { // Duplicate material BabylonPBRMetallicRoughnessMaterial babylonMaterialCloned = DuplicateMaterial(babylonMaterial, materialDuplicationData); // Store duplicated material too babylonScene.MaterialsList.Add(babylonMaterialCloned); } } if (babylonMaterial.transparencyMode == (int)BabylonPBRMetallicRoughnessMaterial.TransparencyMode.ALPHATEST) { // Set the alphaCutOff value explicitely to avoid different interpretations on different engines // Use the glTF default value rather than the babylon one babylonMaterial.alphaCutOff = 0.5f; } if (babylonAttributesDependencyNode == null) { // Create Babylon Material dependency node babylonAiStandardSurfaceMaterialNode.Create(materialDependencyNode); // Retreive Babylon Material dependency node babylonAttributesDependencyNode = getBabylonMaterialNode(materialDependencyNode); } if (babylonAttributesDependencyNode != null) { // Ensure all attributes are setup babylonAiStandardSurfaceMaterialNode.Init(babylonAttributesDependencyNode, babylonMaterial); RaiseVerbose("Babylon Attributes of " + babylonAttributesDependencyNode.name, 2); // Common attributes ExportCommonBabylonAttributes(babylonAttributesDependencyNode, babylonMaterial); babylonMaterial.doubleSided = !babylonMaterial.backFaceCulling; babylonMaterial._unlit = babylonMaterial.isUnlit; } if (fullPBR) { var fullPBRMaterial = new BabylonPBRMaterial(babylonMaterial); babylonScene.MaterialsList.Add(fullPBRMaterial); } else { babylonScene.MaterialsList.Add(babylonMaterial); } } else { RaiseWarning("Unsupported material type '" + materialObject.apiType + "' for material named '" + materialDependencyNode.name + "'", 2); } }
private BabylonMaterial DumpStandardMaterial(Material material, Renderer renderer) { var materialNotSupported = false; if (!materialsDictionary.ContainsKey(material.name)) { var bMat = new BabylonStandardMaterial { name = material.name, id = Guid.NewGuid().ToString(), diffuse = new float[4], specular = new float[4] }; bMat.diffuse[0] = 1.0f; bMat.diffuse[1] = 1.0f; bMat.diffuse[2] = 1.0f; bMat.diffuse[3] = 1.0f; if (material.HasProperty("_Color")) { bMat.diffuse = material.color.ToFloat(); } if (material.HasProperty("_SpecColor")) { var specColor = material.GetColor("_SpecColor"); bMat.specular = specColor.ToFloat(); } if (material.HasProperty("_Shininess")) { var specShininess = material.GetFloat("_Shininess"); bMat.specularPower = specShininess * 128; } if (material.HasProperty("_Emission")) { var emissiveColor = material.GetColor("_Emission"); bMat.emissive = emissiveColor.ToFloat(); } if (material.mainTexture && material.mainTexture.GetType().FullName == "UnityEngine.ProceduralTexture") { materialNotSupported = true; Debug.LogWarning("ProceduralTexture: " + material.mainTexture.name + " not supported by Babylon.js"); } if (material.mainTexture && !(materialNotSupported)) { var mainTexturePath = AssetDatabase.GetAssetPath(material.mainTexture); bMat.diffuseTexture = new BabylonTexture { uScale = material.mainTextureScale.x, vScale = material.mainTextureScale.y, uOffset = material.mainTextureOffset.x, vOffset = material.mainTextureOffset.y }; var mainTexture2D = material.mainTexture as Texture2D; CopyTexture(mainTexturePath, mainTexture2D, bMat.diffuseTexture); var alphaCuttOff = 0f; if (material.HasProperty("_Cutoff")) { alphaCuttOff = material.GetFloat("_Cutoff"); } if ((mainTexture2D && mainTexture2D.alphaIsTransparency) || alphaCuttOff > 0) { bMat.diffuseTexture.hasAlpha = true; bMat.backFaceCulling = false; } bMat.diffuse[0] = 1.0f; bMat.diffuse[1] = 1.0f; bMat.diffuse[2] = 1.0f; bMat.diffuse[3] = 1.0f; } bMat.bumpTexture = DumpTextureFromMaterial(material, "_BumpMap"); bMat.emissiveTexture = DumpTextureFromMaterial(material, "_Illum"); bMat.ambientTexture = DumpTextureFromMaterial(material, "_LightMap"); bMat.reflectionTexture = DumpTextureFromMaterial(material, "_Cube"); if (bMat.ambientTexture == null && renderer.lightmapIndex >= 0 && renderer.lightmapIndex != 255 && LightmapSettings.lightmaps.Length > renderer.lightmapIndex) { var lightmap = LightmapSettings.lightmaps[renderer.lightmapIndex].lightmapFar; bMat.lightmapTexture = DumpTexture(lightmap, isLightmap: true); bMat.lightmapTexture.coordinatesIndex = 1; bMat.useLightmapAsShadowmap = true; bMat.lightmapTexture.uScale = renderer.lightmapScaleOffset.x; bMat.lightmapTexture.vScale = renderer.lightmapScaleOffset.y; bMat.lightmapTexture.uOffset = renderer.lightmapScaleOffset.z; bMat.lightmapTexture.vOffset = renderer.lightmapScaleOffset.w; } materialsDictionary.Add(bMat.name, bMat); return(bMat); } return(materialsDictionary[material.name]); }
private void ExportMaterial(IIGameMaterial materialNode, BabylonScene babylonScene) { var name = materialNode.MaterialName; var id = materialNode.MaxMaterial.GetGuid().ToString(); RaiseMessage(name, 1); // --- prints --- #region prints { RaiseVerbose("materialNode.MaterialClass=" + materialNode.MaterialClass, 2); RaiseVerbose("materialNode.NumberOfTextureMaps=" + materialNode.NumberOfTextureMaps, 2); var propertyContainer = materialNode.IPropertyContainer; RaiseVerbose("propertyContainer=" + propertyContainer, 2); if (propertyContainer != null) { RaiseVerbose("propertyContainer.NumberOfProperties=" + propertyContainer.NumberOfProperties, 3); for (int i = 0; i < propertyContainer.NumberOfProperties; i++) { var prop = propertyContainer.GetProperty(i); if (prop != null) { RaiseVerbose("propertyContainer.GetProperty(" + i + ")=" + prop.Name, 3); switch (prop.GetType_) { case PropType.StringProp: string propertyString = ""; RaiseVerbose("prop.GetPropertyValue(ref propertyString, 0)=" + prop.GetPropertyValue(ref propertyString, 0), 4); RaiseVerbose("propertyString=" + propertyString, 4); break; case PropType.IntProp: int propertyInt = 0; RaiseVerbose("prop.GetPropertyValue(ref propertyInt, 0)=" + prop.GetPropertyValue(ref propertyInt, 0), 4); RaiseVerbose("propertyInt=" + propertyInt, 4); break; case PropType.FloatProp: float propertyFloat = 0; RaiseVerbose("prop.GetPropertyValue(ref propertyFloat, 0)=" + prop.GetPropertyValue(ref propertyFloat, 0, true), 4); RaiseVerbose("propertyFloat=" + propertyFloat, 4); RaiseVerbose("prop.GetPropertyValue(ref propertyFloat, 0)=" + prop.GetPropertyValue(ref propertyFloat, 0, false), 4); RaiseVerbose("propertyFloat=" + propertyFloat, 4); break; case PropType.Point3Prop: IPoint3 propertyPoint3 = Loader.Global.Point3.Create(0, 0, 0); RaiseVerbose("prop.GetPropertyValue(ref propertyPoint3, 0)=" + prop.GetPropertyValue(propertyPoint3, 0), 4); RaiseVerbose("propertyPoint3=" + Point3ToString(propertyPoint3), 4); break; case PropType.Point4Prop: IPoint4 propertyPoint4 = Loader.Global.Point4.Create(0, 0, 0, 0); RaiseVerbose("prop.GetPropertyValue(ref propertyPoint4, 0)=" + prop.GetPropertyValue(propertyPoint4, 0), 4); RaiseVerbose("propertyPoint4=" + Point4ToString(propertyPoint4), 4); break; case PropType.UnknownProp: default: RaiseVerbose("Unknown property type", 4); break; } } else { RaiseVerbose("propertyContainer.GetProperty(" + i + ") IS NULL", 3); } } } } #endregion if (materialNode.SubMaterialCount > 0) { var babylonMultimaterial = new BabylonMultiMaterial { name = name, id = id }; var guids = new List <string>(); for (var index = 0; index < materialNode.SubMaterialCount; index++) { var subMat = materialNode.GetSubMaterial(index); if (subMat != null) { guids.Add(subMat.MaxMaterial.GetGuid().ToString()); if (!referencedMaterials.Contains(subMat)) { referencedMaterials.Add(subMat); ExportMaterial(subMat, babylonScene); } } else { guids.Add(Guid.Empty.ToString()); } } babylonMultimaterial.materials = guids.ToArray(); babylonScene.MultiMaterialsList.Add(babylonMultimaterial); return; } var stdMat = materialNode.MaxMaterial.GetParamBlock(0).Owner as IStdMat2; if (stdMat != null) { var isSelfIllumColor = materialNode.MaxMaterial.GetSelfIllumColorOn(0, false); var babylonMaterial = new BabylonStandardMaterial { name = name, id = id, ambient = materialNode.MaxMaterial.GetAmbient(0, false).ToArray(), diffuse = materialNode.MaxMaterial.GetDiffuse(0, false).ToArray(), specular = materialNode.MaxMaterial.GetSpecular(0, false).Scale(materialNode.MaxMaterial.GetShinStr(0, false)), specularPower = materialNode.MaxMaterial.GetShininess(0, false) * 256, emissive = isSelfIllumColor ? materialNode.MaxMaterial.GetSelfIllumColor(0, false).ToArray() : materialNode.MaxMaterial.GetDiffuse(0, false).Scale(materialNode.MaxMaterial.GetSelfIllum(0, false)), // compute the pre-multiplied emissive color alpha = 1.0f - materialNode.MaxMaterial.GetXParency(0, false) }; // If Self-Illumination color checkbox is checked // Then self-illumination is assumed to be pre-multiplied // Otherwise self-illumination needs to be multiplied with diffuse // linkEmissiveWithDiffuse attribute tells the Babylon engine to perform such multiplication babylonMaterial.linkEmissiveWithDiffuse = !isSelfIllumColor; // useEmissiveAsIllumination attribute tells the Babylon engine to use pre-multiplied emissive as illumination babylonMaterial.useEmissiveAsIllumination = isSelfIllumColor; // Store the emissive value (before multiplication) for gltf babylonMaterial.selfIllum = materialNode.MaxMaterial.GetSelfIllum(0, false); babylonMaterial.backFaceCulling = !stdMat.TwoSided; babylonMaterial.wireframe = stdMat.Wire; // Textures BabylonFresnelParameters fresnelParameters; babylonMaterial.ambientTexture = ExportTexture(stdMat, 0, out fresnelParameters, babylonScene); // Ambient babylonMaterial.diffuseTexture = ExportTexture(stdMat, 1, out fresnelParameters, babylonScene); // Diffuse if (fresnelParameters != null) { babylonMaterial.diffuseFresnelParameters = fresnelParameters; } babylonMaterial.specularTexture = ExportTexture(stdMat, 2, out fresnelParameters, babylonScene); // Specular babylonMaterial.emissiveTexture = ExportTexture(stdMat, 5, out fresnelParameters, babylonScene); // Emissive if (fresnelParameters != null) { babylonMaterial.emissiveFresnelParameters = fresnelParameters; if (babylonMaterial.emissive[0] == 0 && babylonMaterial.emissive[1] == 0 && babylonMaterial.emissive[2] == 0 && babylonMaterial.emissiveTexture == null) { babylonMaterial.emissive = new float[] { 1, 1, 1 }; } } babylonMaterial.opacityTexture = ExportTexture(stdMat, 6, out fresnelParameters, babylonScene, false, true); // Opacity if (fresnelParameters != null) { babylonMaterial.opacityFresnelParameters = fresnelParameters; if (babylonMaterial.alpha == 1 && babylonMaterial.opacityTexture == null) { babylonMaterial.alpha = 0; } } babylonMaterial.bumpTexture = ExportTexture(stdMat, 8, out fresnelParameters, babylonScene); // Bump babylonMaterial.reflectionTexture = ExportTexture(stdMat, 9, out fresnelParameters, babylonScene, true); // Reflection if (fresnelParameters != null) { if (babylonMaterial.reflectionTexture == null) { RaiseWarning("Fallout cannot be used with reflection channel without a texture", 2); } else { babylonMaterial.reflectionFresnelParameters = fresnelParameters; } } // Constraints if (babylonMaterial.diffuseTexture != null) { babylonMaterial.diffuse = new[] { 1.0f, 1.0f, 1.0f }; } if (babylonMaterial.emissiveTexture != null) { babylonMaterial.emissive = new float[] { 0, 0, 0 }; } if (babylonMaterial.opacityTexture != null && babylonMaterial.diffuseTexture != null && babylonMaterial.diffuseTexture.name == babylonMaterial.opacityTexture.name && babylonMaterial.diffuseTexture.hasAlpha && !babylonMaterial.opacityTexture.getAlphaFromRGB) { // This is a alpha testing purpose babylonMaterial.opacityTexture = null; babylonMaterial.diffuseTexture.hasAlpha = true; RaiseWarning("Opacity texture was removed because alpha from diffuse texture can be use instead", 2); RaiseWarning("If you do not want this behavior, just set Alpha Source = None on your diffuse texture", 2); } babylonScene.MaterialsList.Add(babylonMaterial); } // TODO - Find another way to detect if material is physical else if (materialNode.MaterialClass.ToLower() == "physical material" || // English materialNode.MaterialClass.ToLower() == "physisches material" || // German // TODO - check if translation is ok materialNode.MaterialClass.ToLower() == "matériau physique") // French { var propertyContainer = materialNode.IPropertyContainer; var babylonMaterial = new BabylonPBRMetallicRoughnessMaterial { name = name, id = id }; // --- Global --- // Alpha //var alphaFromXParency = 1.0f - materialNode.MaxMaterial.GetXParency(0, false); var alphaFromPropertyContainer = 1.0f - propertyContainer.GetFloatProperty(17); //RaiseMessage("alphaFromXParency=" + alphaFromXParency, 2); //RaiseMessage("alphaFromPropertyContainer=" + alphaFromPropertyContainer, 2); babylonMaterial.alpha = alphaFromPropertyContainer; babylonMaterial.baseColor = materialNode.MaxMaterial.GetDiffuse(0, false).ToArray(); babylonMaterial.metallic = propertyContainer.GetFloatProperty(6); babylonMaterial.roughness = propertyContainer.GetFloatProperty(4); var invertRoughness = propertyContainer.GetBoolProperty(5); if (invertRoughness) { // Inverse roughness babylonMaterial.roughness = 1 - babylonMaterial.roughness; } // Self illumination is computed from emission color, luminance, temperature and weight babylonMaterial.emissive = materialNode.MaxMaterial.GetSelfIllumColorOn(0, false) ? materialNode.MaxMaterial.GetSelfIllumColor(0, false).ToArray() : materialNode.MaxMaterial.GetDiffuse(0, false).Scale(materialNode.MaxMaterial.GetSelfIllum(0, false)); // --- Textures --- babylonMaterial.baseTexture = ExportBaseColorAlphaTexture(materialNode, babylonMaterial.baseColor, babylonMaterial.alpha, babylonScene, name); babylonMaterial.metallicRoughnessTexture = ExportMetallicRoughnessTexture(materialNode, babylonMaterial.metallic, babylonMaterial.roughness, babylonScene, name, invertRoughness); var normalMapAmount = propertyContainer.GetFloatProperty(91); babylonMaterial.normalTexture = ExportPBRTexture(materialNode, 30, babylonScene, normalMapAmount); babylonMaterial.emissiveTexture = ExportPBRTexture(materialNode, 17, babylonScene); // Use diffuse roughness map as ambient occlusion babylonMaterial.occlusionTexture = ExportPBRTexture(materialNode, 6, babylonScene); // Constraints if (babylonMaterial.baseTexture != null) { babylonMaterial.baseColor = new[] { 1.0f, 1.0f, 1.0f }; babylonMaterial.alpha = 1.0f; } if (babylonMaterial.alpha != 1.0f || (babylonMaterial.baseTexture != null && babylonMaterial.baseTexture.hasAlpha)) { babylonMaterial.transparencyMode = (int)BabylonPBRMetallicRoughnessMaterial.TransparencyMode.ALPHABLEND; } if (babylonMaterial.emissiveTexture != null) { babylonMaterial.emissive = new[] { 1.0f, 1.0f, 1.0f }; } if (babylonMaterial.metallicRoughnessTexture != null) { babylonMaterial.metallic = 1.0f; babylonMaterial.roughness = 1.0f; } babylonScene.MaterialsList.Add(babylonMaterial); } else { RaiseWarning("Unsupported material type: " + materialNode.MaterialClass, 2); } }
static void Main(string[] args) { CheckArgs(args); var pathcol = @".\"; if (!File.Exists(pathcol + ColorFileName)) { if (File.Exists(Path + ColorFileName)) { pathcol = Path; } else { Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine("Error: can't find the color description file"); Console.ResetColor(); WriteUsage(); return; } } // LoadColors myColor = new LoadColors(@"C:\Repos\LegoConvertDat\LegoConvertDat", @"ldconfig.ldr"); LoadColors myColor = new LoadColors(pathcol, ColorFileName); if (FileNames == null) { Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine("Error: no file to convert"); Console.ResetColor(); WriteUsage(); return; } foreach (var FileName in FileNames) { if (FileName == "") { continue; } var loader = new Loader(RootPath, Path, FileName, HiQuality); var poly = loader.Polygones; Console.WriteLine("Creating babylon object"); BabylonScene babylonScene = new BabylonScene(Path); babylonScene.producer = new BabylonProducer { name = "LDraw2Babylon", exporter_version = "1.0", file = FileName, version = "1.0" }; babylonScene.autoClear = true; babylonScene.clearColor = new float[] { 0.2f, 0.2f, 0.3f }; babylonScene.ambientColor = new float[] { 0.0f, 0.0f, 0.0f }; babylonScene.gravity = new float[] { 0, 0, -0.9f }; //Camera //BabylonCamera mainCamera = new BabylonCamera(); //mainCamera.name = "Default"; //mainCamera.id = mainCamera.name; //babylonScene.cameras = new BabylonCamera[] { mainCamera }; //babylonScene.activeCameraID = mainCamera.id; //fog babylonScene.fogColor = null; babylonScene.fogDensity = 0; babylonScene.fogEnd = 0; babylonScene.fogMode = 0; babylonScene.fogStart = 0; //light //dBabylonLight babylonLight = new BabylonLight(); //babylonScene.lights = new BabylonLight[] { babylonLight }; Console.WriteLine("Creating lights and cameras"); babylonScene.Prepare(true, true); Console.WriteLine("Creating colors and textures"); // Materials //Create 1 material per Lego color // TODO : need to test specific materials and create the right material List <BabylonStandardMaterial> babMaterial = new List <BabylonStandardMaterial>(); var MatCol = poly.Select(x => x.Color).Distinct(); foreach (var col in MatCol) { BabylonStandardMaterial babylonMaterial = new BabylonStandardMaterial(); babylonMaterial.name = $"Mat_{col.ToString()}"; babylonMaterial.backFaceCulling = false; babylonMaterial.id = babylonMaterial.name; babylonMaterial.specular = new float[] { 0.2f, 0.2f, 0.2f }; babylonMaterial.diffuse = new float[] { (float)(myColor.Colors.Where(x => x.Code == col).First().Color.R / 255.0), (float)(myColor.Colors.Where(x => x.Code == col).First().Color.G / 255.0), (float)(myColor.Colors.Where(x => x.Code == col).First().Color.B / 255.0) }; if (myColor.Colors.Where(x => x.Code == col).First()?.Alpha == 1) { babylonMaterial.alpha = 0.5f; } babylonMaterial.twoSidedLighting = true; babMaterial.Add(babylonMaterial); } babylonScene.materials = babMaterial.ToArray(); Console.WriteLine("Creating meshes"); //Mesh List <BabylonMesh> babMesh = new List <BabylonMesh>(); foreach (var col in MatCol) { #if DEBUG float minX = float.MaxValue; float minY = float.MaxValue; float minZ = float.MaxValue; float maxX = float.MinValue; float maxY = float.MinValue; float maxZ = float.MinValue; #endif BabylonMesh mesh = new BabylonMesh(); mesh.id = FileName + col.ToString(); mesh.name = FileName + col.ToString(); mesh.billboardMode = 0; //linking the material with the color mesh.materialId = $"Mat_{col.ToString()}"; var polcol = poly.Where(x => x.Color == col).ToList(); if (!polcol.Any()) { continue; } //Create the points, indices and normales //please note the code is not optimized to suppress non necessary points mesh.positions = new float[polcol.Count * 9]; mesh.indices = new int[polcol.Count * 3 * 2]; mesh.normals = new float[polcol.Count * 9 * 2]; //Create all the vertice for the specific color for (int i = 0; i < polcol.Count; i++) { var normal = polcol[i].GetNormal(); for (int j = 0; j < 3; j++) { #if DEBUG if (polcol[i].Points(j).X < minX) { minX = polcol[i].Points(j).X; } if (polcol[i].Points(j).Y < minY) { minY = polcol[i].Points(j).Y; } if (polcol[i].Points(j).Z < minZ) { minZ = polcol[i].Points(j).Z; } if (polcol[i].Points(j).X > maxX) { maxX = polcol[i].Points(j).X; } if (polcol[i].Points(j).Y > maxY) { maxY = polcol[i].Points(j).Y; } if (polcol[i].Points(j).Z > maxZ) { maxZ = polcol[i].Points(j).Z; } #endif //Get the point positions mesh.positions[i * 9 + j * 3] = polcol[i].Points(j).X; mesh.positions[i * 9 + 1 + j * 3] = -polcol[i].Points(j).Y; mesh.positions[i * 9 + 2 + j * 3] = polcol[i].Points(j).Z; //add the normals mesh.normals[i * 9 + j * 3] = normal.X; mesh.normals[i * 9 + 1 + j * 3] = normal.Y; mesh.normals[i * 9 + 2 + j * 3] = normal.Z; } //create indices mesh.indices[i * 3] = i * 3; mesh.indices[i * 3 + 1] = i * 3 + 1; mesh.indices[i * 3 + 2] = i * 3 + 2; } babMesh.Add(mesh); #if DEBUG Console.WriteLine($"Min X: {minX} Y: {minY} Z:{minZ}"); Console.WriteLine($"Max X: {maxX} Y: {maxY} Z:{maxZ}"); #endif } //create the Array babylonScene.meshes = babMesh.ToArray(); Console.WriteLine("Serializing babylon file"); var filewithoutext = FileName.Substring(0, FileName.Length - FileName.LastIndexOf('.')); var ser = JsonConvert.SerializeObject(babylonScene); Console.WriteLine("Saving babylon file"); StreamWriter firstfile = new StreamWriter(OutputPath + filewithoutext + ".babylon"); //Saving the file firstfile.Write(ser); firstfile.Close(); firstfile.Dispose(); //System.Diagnostics.Process.Start($"http://localhost:21175/index-2.html?file={filewithoutext}.babylon"); //Console.ReadKey(); } }