Пример #1
0
        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);
        }
Пример #3
0
        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);
        }
Пример #11
0
        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);
            }
        }
Пример #12
0
        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);
            }
        }
Пример #14
0
        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);
        }
Пример #16
0
        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;
            }
        }
Пример #17
0
        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);
            }
        }
Пример #19
0
        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);
            }
        }
Пример #20
0
        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]);
        }
Пример #21
0
        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);
            }
        }
Пример #22
0
        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();
            }
        }