Esempio n. 1
0
        /// <summary>
        /// Extract a material and its linked texture, if any.
        /// </summary>
        private static void ExtractMaterial(MayaM2Mesh mesh, MObject material)
        {
            var fnShader = new MFnLambertShader(material);
            // Get lambert out of the shader
            var strName = fnShader.name;

            MGlobal.displayInfo("Detected material : " + strName + " of type " + material.apiTypeStr);
            //TODO use this type

            // ReSharper disable once UnusedVariable
            var clrDiffuse = fnShader.color;
            // ReSharper disable once UnusedVariable
            var clrAmbient = fnShader.ambientColor;

            if (material.hasFn(MFn.Type.kReflect))
            {
                var fnReflectShader = new MFnReflectShader(material);
                // ReSharper disable once UnusedVariable
                var clrSpec = fnReflectShader.specularColor;
            }

            // Look for textures at the color plug
            var colorPlug       = fnShader.findPlug("color");
            var fileTextureIter = new MItDependencyGraph(colorPlug.node, MFn.Type.kFileTexture,
                                                         MItDependencyGraph.Direction.kUpstream, MItDependencyGraph.Traversal.kDepthFirst,
                                                         MItDependencyGraph.Level.kNodeLevel);

            while (!fileTextureIter.isDone)
            {
                //TODO hardcoded textures
                var nodeFn = new MFnDependencyNode(fileTextureIter.thisNode());

                var    fileNamePlug = nodeFn.findPlug("fileTextureName");
                string textureFileName;
                fileNamePlug.getValue(out textureFileName);
                MGlobal.displayInfo("\t Texture found : " + textureFileName);

                var wrapUPlug = nodeFn.findPlug("wrapU");
                var wrapU     = false;
                wrapUPlug.getValue(ref wrapU);
                var wrapVPlug = nodeFn.findPlug("wrapV");
                var wrapV     = false;
                wrapVPlug.getValue(ref wrapV);
                var tex = new MayaM2Texture
                {
                    WrapU = wrapU,
                    WrapV = wrapV
                };
                mesh.Textures.Add(tex);
                fileTextureIter.next();//maybe now the loop is fixed
            }
        }
Esempio n. 2
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);
            }
        }
Esempio n. 3
0
        public void Load(string name)
        {
            List <StaticObjectVertex> vertices = GetVertices();
            List <uint> indices = GetIndices();

            MIntArray        polygonIndexCounts = new MIntArray((uint)indices.Count / 3);
            MIntArray        polygonIndices     = new MIntArray((uint)indices.Count);
            MFloatPointArray meshVertices       = new MFloatPointArray((uint)vertices.Count);
            MFloatArray      arrayU             = new MFloatArray((uint)vertices.Count);
            MFloatArray      arrayV             = new MFloatArray((uint)vertices.Count);
            MFnMesh          mesh        = new MFnMesh();
            MDagPath         meshDagPath = new MDagPath();
            MDGModifier      modifier    = new MDGModifier();
            MFnSet           set         = new MFnSet();

            for (int i = 0; i < indices.Count / 3; i++)
            {
                polygonIndexCounts[i] = 3;
            }

            for (int i = 0; i < indices.Count; i++)
            {
                polygonIndices[i] = (int)indices[i];
            }

            for (int i = 0; i < vertices.Count; i++)
            {
                StaticObjectVertex vertex = vertices[i];

                meshVertices[i] = new MFloatPoint(vertex.Position.X, vertex.Position.Y, vertex.Position.Z);
                arrayU[i]       = vertex.UV.X;
                arrayV[i]       = 1 - vertex.UV.Y;
            }

            //Assign mesh data
            mesh.create(vertices.Count, indices.Count / 3, meshVertices, polygonIndexCounts, polygonIndices, arrayU, arrayV, MObject.kNullObj);
            mesh.getPath(meshDagPath);
            mesh.assignUVs(polygonIndexCounts, polygonIndices);

            //Set names
            mesh.setName(name);
            MFnTransform transformNode = new MFnTransform(mesh.parent(0));

            transformNode.setName("transform_" + name);

            //Get render partition
            MFnPartition renderPartition = MayaHelper.FindRenderPartition();

            //Create Materials
            uint startIndex = 0;

            for (int i = 0; i < this.Submeshes.Count; i++)
            {
                MFnDependencyNode   dependencyNode = new MFnDependencyNode();
                MFnLambertShader    lambertShader  = new MFnLambertShader();
                StaticObjectSubmesh submesh        = this.Submeshes[i];

                lambertShader.create(true);
                lambertShader.setName(submesh.Name);
                lambertShader.color = MaterialProvider.GetMayaColor(i);

                MObject shadingEngine = dependencyNode.create("shadingEngine", submesh.Name + "_SG");
                MObject materialInfo  = dependencyNode.create("materialInfo", submesh.Name + "_MaterialInfo");
                MPlug   partitionPlug = new MFnDependencyNode(shadingEngine).findPlug("partition");
                MPlug   setsPlug      = MayaHelper.FindFirstNotConnectedElement(renderPartition.findPlug("sets"));
                modifier.connect(partitionPlug, setsPlug);

                MPlug outColorPlug      = lambertShader.findPlug("outColor");
                MPlug surfaceShaderPlug = new MFnDependencyNode(shadingEngine).findPlug("surfaceShader");
                modifier.connect(outColorPlug, surfaceShaderPlug);

                MPlug messagePlug      = new MFnDependencyNode(shadingEngine).findPlug("message");
                MPlug shadingGroupPlug = new MFnDependencyNode(materialInfo).findPlug("shadingGroup");
                modifier.connect(messagePlug, shadingGroupPlug);

                modifier.doIt();

                MFnSingleIndexedComponent component = new MFnSingleIndexedComponent();
                MObject   faceComponent             = component.create(MFn.Type.kMeshPolygonComponent);
                MIntArray groupPolygonIndices       = new MIntArray();
                uint      endIndex = (startIndex + (uint)submesh.Indices.Count) / 3;
                for (uint j = startIndex / 3; j < endIndex; j++)
                {
                    groupPolygonIndices.append((int)j);
                }
                component.addElements(groupPolygonIndices);

                set.setObject(shadingEngine);
                set.addMember(meshDagPath, faceComponent);

                startIndex += (uint)submesh.Indices.Count;
            }

            mesh.updateSurface();
        }
        public void Load(string name, SKLFile skl = null)
        {
            MIntArray        polygonIndexCounts = new MIntArray((uint)this.Indices.Count / 3);
            MIntArray        polygonIndices     = new MIntArray((uint)this.Indices.Count);
            MFloatPointArray vertices           = new MFloatPointArray((uint)this.Vertices.Count);
            MFloatArray      arrayU             = new MFloatArray((uint)this.Vertices.Count);
            MFloatArray      arrayV             = new MFloatArray((uint)this.Vertices.Count);
            MVectorArray     normals            = new MVectorArray((uint)this.Vertices.Count);
            MIntArray        normalIndices      = new MIntArray((uint)this.Vertices.Count);
            MFnMesh          mesh        = new MFnMesh();
            MDagPath         meshDagPath = new MDagPath();
            MDGModifier      modifier    = new MDGModifier();
            MFnSet           set         = new MFnSet();

            for (int i = 0; i < this.Indices.Count / 3; i++)
            {
                polygonIndexCounts[i] = 3;
            }

            for (int i = 0; i < this.Indices.Count; i++)
            {
                polygonIndices[i] = this.Indices[i];
            }

            for (int i = 0; i < this.Vertices.Count; i++)
            {
                SKNVertex vertex = this.Vertices[i];

                vertices[i]      = new MFloatPoint(vertex.Position.X, vertex.Position.Y, vertex.Position.Z);
                arrayU[i]        = vertex.UV.X;
                arrayV[i]        = 1 - vertex.UV.Y;
                normals[i]       = new MVector(vertex.Normal.X, vertex.Normal.Y, vertex.Normal.Z);
                normalIndices[i] = i;
            }

            //Assign mesh data
            mesh.create(this.Vertices.Count, this.Indices.Count / 3, vertices, polygonIndexCounts, polygonIndices, arrayU, arrayV, MObject.kNullObj);
            mesh.setVertexNormals(normals, normalIndices);
            mesh.getPath(meshDagPath);
            mesh.assignUVs(polygonIndexCounts, polygonIndices);

            //Set names
            mesh.setName(name);
            MFnTransform transformNode = new MFnTransform(mesh.parent(0));

            transformNode.setName("transform_" + name);

            //Get render partition
            MGlobal.displayInfo("SKNFile:Load - Searching for Render Partition");
            MItDependencyNodes itDependencyNodes = new MItDependencyNodes(MFn.Type.kPartition);
            MFnPartition       renderPartition   = new MFnPartition();
            bool foundRenderPartition            = false;

            for (; !itDependencyNodes.isDone; itDependencyNodes.next())
            {
                renderPartition.setObject(itDependencyNodes.thisNode);
                MGlobal.displayInfo("SKNFile:Load - Iterating through partition: " + renderPartition.name + " IsRenderPartition: " + renderPartition.isRenderPartition);
                if (renderPartition.name == "renderPartition" && renderPartition.isRenderPartition)
                {
                    MGlobal.displayInfo("SKNFile:Load - Found render partition");
                    foundRenderPartition = true;
                    break;
                }
            }


            //Create Materials
            for (int i = 0; i < this.Submeshes.Count; i++)
            {
                MFnDependencyNode dependencyNode = new MFnDependencyNode();
                MFnLambertShader  lambertShader  = new MFnLambertShader();
                SKNSubmesh        submesh        = this.Submeshes[i];
                MObject           shader         = lambertShader.create(true);

                lambertShader.setName(submesh.Name);
                lambertShader.color = MaterialProvider.GetMayaColor(i);

                MObject shadingEngine = dependencyNode.create("shadingEngine", submesh.Name + "_SG");
                MObject materialInfo  = dependencyNode.create("materialInfo", submesh.Name + "_MaterialInfo");
                if (foundRenderPartition)
                {
                    MPlug partitionPlug = new MFnDependencyNode(shadingEngine).findPlug("partition");
                    MPlug setsPlug      = MayaHelper.FindFirstNotConnectedElement(renderPartition.findPlug("sets"));
                    modifier.connect(partitionPlug, setsPlug);
                }
                else
                {
                    MGlobal.displayInfo("SKNFile:Load - Couldn't find Render Partition for mesh: " + name + "." + submesh.Name);
                }

                MPlug outColorPlug      = lambertShader.findPlug("outColor");
                MPlug surfaceShaderPlug = new MFnDependencyNode(shadingEngine).findPlug("surfaceShader");
                modifier.connect(outColorPlug, surfaceShaderPlug);

                MPlug messagePlug      = new MFnDependencyNode(shadingEngine).findPlug("message");
                MPlug shadingGroupPlug = new MFnDependencyNode(materialInfo).findPlug("shadingGroup");
                modifier.connect(messagePlug, shadingGroupPlug);

                modifier.doIt();

                MFnSingleIndexedComponent component = new MFnSingleIndexedComponent();
                MObject   faceComponent             = component.create(MFn.Type.kMeshPolygonComponent);
                MIntArray groupPolygonIndices       = new MIntArray();
                uint      endIndex = (submesh.StartIndex + submesh.IndexCount) / 3;
                for (uint j = submesh.StartIndex / 3; j < endIndex; j++)
                {
                    groupPolygonIndices.append((int)j);
                }
                component.addElements(groupPolygonIndices);

                set.setObject(shadingEngine);
                set.addMember(meshDagPath, faceComponent);
            }

            if (skl == null)
            {
                mesh.updateSurface();
            }
            else
            {
                MFnSkinCluster skinCluster             = new MFnSkinCluster();
                MSelectionList jointPathsSelectionList = new MSelectionList();

                jointPathsSelectionList.add(meshDagPath);
                for (int i = 0; i < skl.Influences.Count; i++)
                {
                    short    jointIndex = skl.Influences[i];
                    SKLJoint joint      = skl.Joints[jointIndex];
                    jointPathsSelectionList.add(skl.JointDagPaths[jointIndex]);

                    MGlobal.displayInfo(string.Format("SKNFile:Load:Bind - Added joint [{0}] {1} to binding selection", joint.ID, joint.Name));
                }

                MGlobal.selectCommand(jointPathsSelectionList);
                MGlobal.executeCommand("skinCluster -mi 4 -tsb -n skinCluster_" + name);

                MPlug      inMeshPlug        = mesh.findPlug("inMesh");
                MPlugArray inMeshConnections = new MPlugArray();
                inMeshPlug.connectedTo(inMeshConnections, true, false);

                if (inMeshConnections.length == 0)
                {
                    MGlobal.displayError("SKNFile:Load:Bind - Failed to find the created Skin Cluster");
                    throw new Exception("SKNFile:Load:Bind - Failed to find the created Skin Cluster");
                }

                MPlug         outputGeometryPlug = inMeshConnections[0];
                MDagPathArray influencesDagPaths = new MDagPathArray();

                skinCluster.setObject(outputGeometryPlug.node);
                skinCluster.influenceObjects(influencesDagPaths);

                MIntArray influenceIndices = new MIntArray((uint)skl.Influences.Count);
                for (int i = 0; i < skl.Influences.Count; i++)
                {
                    MDagPath influencePath = skl.JointDagPaths[skl.Influences[i]];

                    for (int j = 0; j < skl.Influences.Count; j++)
                    {
                        if (influencesDagPaths[j].partialPathName == influencePath.partialPathName)
                        {
                            influenceIndices[i] = j;
                            MGlobal.displayInfo("SKNReader:Load:Bind - Added Influence Joint: " + i + " -> " + j);
                            break;
                        }
                    }
                }

                MFnSingleIndexedComponent singleIndexedComponent = new MFnSingleIndexedComponent();
                MObject   vertexComponent    = singleIndexedComponent.create(MFn.Type.kMeshVertComponent);
                MIntArray groupVertexIndices = new MIntArray((uint)this.Vertices.Count);

                for (int i = 0; i < this.Vertices.Count; i++)
                {
                    groupVertexIndices[i] = i;
                }
                singleIndexedComponent.addElements(groupVertexIndices);

                MGlobal.executeCommand(string.Format("setAttr {0}.normalizeWeights 0", skinCluster.name));

                MDoubleArray weights = new MDoubleArray((uint)(this.Vertices.Count * skl.Influences.Count));
                for (int i = 0; i < this.Vertices.Count; i++)
                {
                    SKNVertex vertex = this.Vertices[i];

                    for (int j = 0; j < 4; j++)
                    {
                        double weight    = vertex.Weights[j];
                        int    influence = vertex.BoneIndices[j];

                        if (weight != 0)
                        {
                            weights[(i * skl.Influences.Count) + influence] = weight;
                        }
                    }
                }

                skinCluster.setWeights(meshDagPath, vertexComponent, influenceIndices, weights, false);
                MGlobal.executeCommand(string.Format("setAttr {0}.normalizeWeights 1", skinCluster.name));
                MGlobal.executeCommand(string.Format("skinPercent -normalize true {0} {1}", skinCluster.name, mesh.name));
                mesh.updateSurface();
            }
        }
Esempio n. 5
0
        public Material MakeMaterial(MFnMesh fnMesh)
        {
            MaterialGroup matGroup = new MaterialGroup();

            MObjectArray shaders = new MObjectArray();
            MIntArray    indices = new MIntArray();

            fnMesh.getConnectedShaders(0, shaders, indices);
            for (int i = 0; i < shaders.length; i++)
            {
                MFnDependencyNode shaderGroup = new MFnDependencyNode(shaders [i]);
                MPlug             shaderPlug  = shaderGroup.findPlug("surfaceShader");
                MPlugArray        connections = new MPlugArray();
                shaderPlug.connectedTo(connections, true, false);
                for (int u = 0; u < connections.length; u++)
                {
                    MFnDependencyNode depNode = new MFnDependencyNode(connections [u].node);

                    //MPlug colorPlug =depNode.findPlug ("color") ;
                    //MColor mcolor =new MColor () ;
                    ///*MPlugArray cc =new MPlugArray () ;
                    //colorPlug.connectedTo (cc, true , false) ;
                    //if ( cc.length > 0 ) {
                    //    // Plug is driven by an input connection.
                    //    for ( int v =0 ; v < cc.length ; v++ ) {
                    //        MPlug color2Plug =cc [v] ;
                    //        Console.WriteLine (color2Plug.numChildren) ;
                    //        color2Plug.child (0).getValue (mcolor.r) ;
                    //        color2Plug.child (1).getValue (mcolor.g) ;
                    //        color2Plug.child (2).getValue (mcolor.b) ;
                    //        //color2Plug.child (3).getValue (mcolor.a) ;
                    //    }
                    //} else {*/
                    //    mcolor.r =colorPlug.child (0).asFloat () ;
                    //    mcolor.g =colorPlug.child (1).asFloat () ;
                    //    mcolor.b =colorPlug.child (2).asFloat () ;
                    //    //colorPlug.child (3).getValue (mcolor.a) ;
                    ////}

                    //MPlug trPlug =depNode.findPlug ("transparency") ;
                    //float transparency =1.0f - trPlug.child (0).asFloat () ;
                    ////return new DiffuseMaterial (new SolidColorBrush (Color.FromScRgb (transparency, mcolor.r, mcolor.g, mcolor.b))) ;

                    //DiffuseMaterial diffuse =new DiffuseMaterial (new SolidColorBrush (Color.FromScRgb (transparency, mcolor.r, mcolor.g, mcolor.b))) ;
                    //colorPlug =depNode.findPlug ("ambientColor") ;
                    //mcolor.r =colorPlug.child (0).asFloat () ;
                    //mcolor.g =colorPlug.child (1).asFloat () ;
                    //mcolor.b =colorPlug.child (2).asFloat () ;
                    //diffuse.AmbientColor =Color.FromScRgb (transparency, mcolor.r, mcolor.g, mcolor.b) ;
                    //matGroup.Children.Add (diffuse) ;

                    //colorPlug =depNode.findPlug ("specularColor") ;
                    //mcolor.r =colorPlug.child (0).asFloat () ;
                    //mcolor.g =colorPlug.child (1).asFloat () ;
                    //mcolor.b =colorPlug.child (2).asFloat () ;
                    //MPlug powerPlug =depNode.findPlug ("cosinePower") ;

                    //SpecularMaterial specular =new SpecularMaterial (new SolidColorBrush (Color.FromScRgb (1.0f, mcolor.r, mcolor.g, mcolor.b)), powerPlug.asDouble ()) ;
                    //matGroup.Children.Add (specular) ;

                    //EmissiveMaterial emissive =new EmissiveMaterial () ;
                    //matGroup.Children.Add (emissive) ;

                    try {
                        MFnLambertShader lambert = new MFnLambertShader(connections [u].node);

                        SolidColorBrush brush = new SolidColorBrush(Color.FromScRgb(1.0f - lambert.transparency.r, lambert.color.r, lambert.color.g, lambert.color.b));
                        brush.Opacity = 1.0f - lambert.transparency.r;
                        DiffuseMaterial diffuse = new DiffuseMaterial(brush);
                        diffuse.AmbientColor = Color.FromScRgb(1.0f - lambert.ambientColor.a, lambert.ambientColor.r, lambert.ambientColor.g, lambert.ambientColor.b);
                        // no more attributes
                        matGroup.Children.Add(diffuse);

                        // No specular color

                        EmissiveMaterial emissive = new EmissiveMaterial(new SolidColorBrush(Color.FromScRgb(1.0f - lambert.incandescence.a, lambert.incandescence.r, lambert.incandescence.g, lambert.incandescence.b)));
                        // no more attributes
                        matGroup.Children.Add(emissive);
                    } catch {
                    }

                    //try {
                    //    MFnReflectShader reflect =new MFnReflectShader (connections [u].node) ;

                    //    SpecularMaterial specular =new SpecularMaterial (new SolidColorBrush (Color.FromScRgb (1.0f - reflect.specularColor.a, reflect.specularColor.r, reflect.specularColor.g, reflect.specularColor.b)), reflect.cosPower) ;
                    //    // no more attributes
                    //    matGroup.Children.Add (specular) ;
                    //} catch {
                    //}

                    try {
                        MFnPhongShader phong = new MFnPhongShader(connections [u].node);

                        //See Lambert
                        //SolidColorBrush brush =new SolidColorBrush (Color.FromScRgb (1.0f - phong.transparency.r, phong.color.r, phong.color.g, phong.color.b)) ;
                        //brush.Opacity =1.0f - phong.transparency.r ;
                        //DiffuseMaterial diffuse =new DiffuseMaterial (brush) ;
                        //diffuse.AmbientColor =Color.FromScRgb (1.0f - phong.ambientColor.a, phong.ambientColor.r, phong.ambientColor.g, phong.ambientColor.b) ;
                        //// no more attributes
                        //matGroup.Children.Add (diffuse) ;

                        SpecularMaterial specular = new SpecularMaterial(new SolidColorBrush(Color.FromScRgb(1.0f - phong.specularColor.a, phong.specularColor.r, phong.specularColor.g, phong.specularColor.b)), phong.cosPower);
                        // no more attributes
                        matGroup.Children.Add(specular);

                        //See Lambert
                        //EmissiveMaterial emissive =new EmissiveMaterial (new SolidColorBrush (Color.FromScRgb (1.0f - phong.incandescence.a, phong.incandescence.r, phong.incandescence.g, phong.incandescence.b))) ;
                        //// no more attributes
                        //matGroup.Children.Add (emissive) ;
                    } catch {
                    }

                    // todo
                    //try {
                    //    MFnBlinnShader phong =new MFnBlinnShader (connections [u].node) ;

                    //    //See Lambert
                    //    //SolidColorBrush brush =new SolidColorBrush (Color.FromScRgb (1.0f - phong.transparency.r, phong.color.r, phong.color.g, phong.color.b)) ;
                    //    //brush.Opacity =1.0f - phong.transparency.r ;
                    //    //DiffuseMaterial diffuse =new DiffuseMaterial (brush) ;
                    //    //diffuse.AmbientColor = Color.FromScRgb (1.0f - phong.ambientColor.a, phong.ambientColor.r, phong.ambientColor.g, phong.ambientColor.b) ;
                    //    //// no more attributes
                    //    //matGroup.Children.Add (diffuse) ;

                    //    //See Lambert
                    //    //EmissiveMaterial emissive =new EmissiveMaterial (new SolidColorBrush (Color.FromScRgb (1.0f - phong.incandescence.a, phong.incandescence.r, phong.incandescence.g, phong.incandescence.b))) ;
                    //    //// no more attributes
                    //    //matGroup.Children.Add (emissive) ;
                    //} catch {
                    //}
                }
            }

            // Default to Blue
            if (matGroup.Children.Count == 0)
            {
                matGroup.Children.Add(new DiffuseMaterial(new SolidColorBrush(Color.FromRgb(0, 0, 255))));
            }
            return(matGroup);
        }
Esempio n. 6
0
        public Material MakeMaterial(MFnMesh fnMesh)
        {
            MaterialGroup matGroup =new MaterialGroup () ;

            MObjectArray shaders =new MObjectArray() ;
            MIntArray indices =new MIntArray () ;
            fnMesh.getConnectedShaders (0, shaders, indices) ;
            for ( int i =0 ; i < shaders.length ; i++ ) {
                MFnDependencyNode shaderGroup =new MFnDependencyNode (shaders [i]) ;
                MPlug shaderPlug =shaderGroup.findPlug ("surfaceShader") ;
                MPlugArray connections =new MPlugArray () ;
                shaderPlug.connectedTo (connections, true, false) ;
                for ( int u =0 ; u < connections.length ; u++ ) {
                    MFnDependencyNode depNode =new MFnDependencyNode (connections [u].node) ;

                    //MPlug colorPlug =depNode.findPlug ("color") ;
                    //MColor mcolor =new MColor () ;
                    ///*MPlugArray cc =new MPlugArray () ;
                    //colorPlug.connectedTo (cc, true , false) ;
                    //if ( cc.length > 0 ) {
                    //    // Plug is driven by an input connection.
                    //    for ( int v =0 ; v < cc.length ; v++ ) {
                    //        MPlug color2Plug =cc [v] ;
                    //        Console.WriteLine (color2Plug.numChildren) ;
                    //        color2Plug.child (0).getValue (mcolor.r) ;
                    //        color2Plug.child (1).getValue (mcolor.g) ;
                    //        color2Plug.child (2).getValue (mcolor.b) ;
                    //        //color2Plug.child (3).getValue (mcolor.a) ;
                    //    }
                    //} else {*/
                    //    mcolor.r =colorPlug.child (0).asFloat () ;
                    //    mcolor.g =colorPlug.child (1).asFloat () ;
                    //    mcolor.b =colorPlug.child (2).asFloat () ;
                    //    //colorPlug.child (3).getValue (mcolor.a) ;
                    ////}

                    //MPlug trPlug =depNode.findPlug ("transparency") ;
                    //float transparency =1.0f - trPlug.child (0).asFloat () ;
                    ////return new DiffuseMaterial (new SolidColorBrush (Color.FromScRgb (transparency, mcolor.r, mcolor.g, mcolor.b))) ;

                    //DiffuseMaterial diffuse =new DiffuseMaterial (new SolidColorBrush (Color.FromScRgb (transparency, mcolor.r, mcolor.g, mcolor.b))) ;
                    //colorPlug =depNode.findPlug ("ambientColor") ;
                    //mcolor.r =colorPlug.child (0).asFloat () ;
                    //mcolor.g =colorPlug.child (1).asFloat () ;
                    //mcolor.b =colorPlug.child (2).asFloat () ;
                    //diffuse.AmbientColor =Color.FromScRgb (transparency, mcolor.r, mcolor.g, mcolor.b) ;
                    //matGroup.Children.Add (diffuse) ;

                    //colorPlug =depNode.findPlug ("specularColor") ;
                    //mcolor.r =colorPlug.child (0).asFloat () ;
                    //mcolor.g =colorPlug.child (1).asFloat () ;
                    //mcolor.b =colorPlug.child (2).asFloat () ;
                    //MPlug powerPlug =depNode.findPlug ("cosinePower") ;

                    //SpecularMaterial specular =new SpecularMaterial (new SolidColorBrush (Color.FromScRgb (1.0f, mcolor.r, mcolor.g, mcolor.b)), powerPlug.asDouble ()) ;
                    //matGroup.Children.Add (specular) ;

                    //EmissiveMaterial emissive =new EmissiveMaterial () ;
                    //matGroup.Children.Add (emissive) ;

                    try {
                        MFnLambertShader lambert =new MFnLambertShader (connections [u].node) ;

                        SolidColorBrush brush =new SolidColorBrush (Color.FromScRgb (1.0f - lambert.transparency.r, lambert.color.r, lambert.color.g, lambert.color.b)) ;
                        brush.Opacity =1.0f - lambert.transparency.r ;
                        DiffuseMaterial diffuse =new DiffuseMaterial (brush) ;
                        diffuse.AmbientColor =Color.FromScRgb (1.0f - lambert.ambientColor.a, lambert.ambientColor.r, lambert.ambientColor.g, lambert.ambientColor.b) ;
                        // no more attributes
                        matGroup.Children.Add (diffuse) ;

                        // No specular color

                        EmissiveMaterial emissive =new EmissiveMaterial (new SolidColorBrush (Color.FromScRgb (1.0f - lambert.incandescence.a, lambert.incandescence.r, lambert.incandescence.g, lambert.incandescence.b))) ;
                        // no more attributes
                        matGroup.Children.Add (emissive) ;
                    } catch {
                    }

                    //try {
                    //    MFnReflectShader reflect =new MFnReflectShader (connections [u].node) ;

                    //    SpecularMaterial specular =new SpecularMaterial (new SolidColorBrush (Color.FromScRgb (1.0f - reflect.specularColor.a, reflect.specularColor.r, reflect.specularColor.g, reflect.specularColor.b)), reflect.cosPower) ;
                    //    // no more attributes
                    //    matGroup.Children.Add (specular) ;
                    //} catch {
                    //}

                    try {
                        MFnPhongShader phong =new MFnPhongShader (connections [u].node) ;

                        //See Lambert
                        //SolidColorBrush brush =new SolidColorBrush (Color.FromScRgb (1.0f - phong.transparency.r, phong.color.r, phong.color.g, phong.color.b)) ;
                        //brush.Opacity =1.0f - phong.transparency.r ;
                        //DiffuseMaterial diffuse =new DiffuseMaterial (brush) ;
                        //diffuse.AmbientColor =Color.FromScRgb (1.0f - phong.ambientColor.a, phong.ambientColor.r, phong.ambientColor.g, phong.ambientColor.b) ;
                        //// no more attributes
                        //matGroup.Children.Add (diffuse) ;

                        SpecularMaterial specular =new SpecularMaterial (new SolidColorBrush (Color.FromScRgb (1.0f - phong.specularColor.a, phong.specularColor.r, phong.specularColor.g, phong.specularColor.b)), phong.cosPower) ;
                        // no more attributes
                        matGroup.Children.Add (specular) ;

                        //See Lambert
                        //EmissiveMaterial emissive =new EmissiveMaterial (new SolidColorBrush (Color.FromScRgb (1.0f - phong.incandescence.a, phong.incandescence.r, phong.incandescence.g, phong.incandescence.b))) ;
                        //// no more attributes
                        //matGroup.Children.Add (emissive) ;
                    } catch {
                    }

                    // todo
                    //try {
                    //    MFnBlinnShader phong =new MFnBlinnShader (connections [u].node) ;

                    //    //See Lambert
                    //    //SolidColorBrush brush =new SolidColorBrush (Color.FromScRgb (1.0f - phong.transparency.r, phong.color.r, phong.color.g, phong.color.b)) ;
                    //    //brush.Opacity =1.0f - phong.transparency.r ;
                    //    //DiffuseMaterial diffuse =new DiffuseMaterial (brush) ;
                    //    //diffuse.AmbientColor = Color.FromScRgb (1.0f - phong.ambientColor.a, phong.ambientColor.r, phong.ambientColor.g, phong.ambientColor.b) ;
                    //    //// no more attributes
                    //    //matGroup.Children.Add (diffuse) ;

                    //    //See Lambert
                    //    //EmissiveMaterial emissive =new EmissiveMaterial (new SolidColorBrush (Color.FromScRgb (1.0f - phong.incandescence.a, phong.incandescence.r, phong.incandescence.g, phong.incandescence.b))) ;
                    //    //// no more attributes
                    //    //matGroup.Children.Add (emissive) ;
                    //} catch {
                    //}
                }
            }

            // Default to Blue
            if ( matGroup.Children.Count == 0 )
                 matGroup.Children.Add (new DiffuseMaterial (new SolidColorBrush (Color.FromRgb (0, 0, 255)))) ;
            return (matGroup) ;
        }
        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);
            }
        }
Esempio n. 8
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);
            }
        }