static void DumpMultiMaterial(NovaMultiMaterial multiMaterial, BabylonScene babylonScene)
        {
            var babylonMultiMaterial = new BabylonMultiMaterial();

            babylonScene.MultiMaterialsList.Add(babylonMultiMaterial);

            babylonMultiMaterial.name = multiMaterial.Name;
            babylonMultiMaterial.id   = multiMaterial.ID.ToString();

            babylonMultiMaterial.materials = multiMaterial.Materials.Select(material => (material != null ? material.ID.ToString() : "")).ToArray();
        }
Beispiel #2
0
        private void ExportMultiMaterial(string uuidMultiMaterial, List <MFnDependencyNode> materials, BabylonScene babylonScene, bool fullPBR)
        {
            var babylonMultimaterial = new BabylonMultiMaterial {
                id = uuidMultiMaterial
            };

            // Name
            string nameConcatenated = "";
            bool   isFirstTime      = true;
            List <MFnDependencyNode> materialsSorted = new List <MFnDependencyNode>(materials);

            materialsSorted.Sort(new MFnDependencyNodeComparer());
            foreach (MFnDependencyNode material in materialsSorted)
            {
                if (!isFirstTime)
                {
                    nameConcatenated += "_";
                }
                isFirstTime = false;

                nameConcatenated += material.name;
            }
            babylonMultimaterial.name = nameConcatenated;

            // Materials
            var uuids = new List <string>();

            foreach (MFnDependencyNode subMat in materials)
            {
                string uuidSubMat = subMat.uuid().asString();
                uuids.Add(uuidSubMat);

                if (!referencedMaterials.Contains(subMat, new MFnDependencyNodeEqualityComparer()))
                {
                    // Export sub material
                    referencedMaterials.Add(subMat);
                    ExportMaterial(subMat, babylonScene, fullPBR);
                }
            }
            babylonMultimaterial.materials = uuids.ToArray();

            babylonScene.MultiMaterialsList.Add(babylonMultimaterial);
        }
Beispiel #3
0
        private void ExportMaterial(IIGameMaterial materialNode, BabylonScene babylonScene)
        {
            var name = materialNode.MaterialName;
            var id   = materialNode.MaxMaterial.GetGuid().ToString();

            RaiseMessage(name, 1);

            // --- prints ---
            #region prints
            {
                RaiseVerbose("materialNode.MaterialClass=" + materialNode.MaterialClass, 2);
                RaiseVerbose("materialNode.NumberOfTextureMaps=" + materialNode.NumberOfTextureMaps, 2);

                var propertyContainer = materialNode.IPropertyContainer;
                RaiseVerbose("propertyContainer=" + propertyContainer, 2);
                if (propertyContainer != null)
                {
                    RaiseVerbose("propertyContainer.NumberOfProperties=" + propertyContainer.NumberOfProperties, 3);
                    for (int i = 0; i < propertyContainer.NumberOfProperties; i++)
                    {
                        var prop = propertyContainer.GetProperty(i);
                        if (prop != null)
                        {
                            RaiseVerbose("propertyContainer.GetProperty(" + i + ")=" + prop.Name, 3);
                            switch (prop.GetType_)
                            {
                            case PropType.StringProp:
                                string propertyString = "";
                                RaiseVerbose("prop.GetPropertyValue(ref propertyString, 0)=" + prop.GetPropertyValue(ref propertyString, 0), 4);
                                RaiseVerbose("propertyString=" + propertyString, 4);
                                break;

                            case PropType.IntProp:
                                int propertyInt = 0;
                                RaiseVerbose("prop.GetPropertyValue(ref propertyInt, 0)=" + prop.GetPropertyValue(ref propertyInt, 0), 4);
                                RaiseVerbose("propertyInt=" + propertyInt, 4);
                                break;

                            case PropType.FloatProp:
                                float propertyFloat = 0;
                                RaiseVerbose("prop.GetPropertyValue(ref propertyFloat, 0)=" + prop.GetPropertyValue(ref propertyFloat, 0, true), 4);
                                RaiseVerbose("propertyFloat=" + propertyFloat, 4);
                                RaiseVerbose("prop.GetPropertyValue(ref propertyFloat, 0)=" + prop.GetPropertyValue(ref propertyFloat, 0, false), 4);
                                RaiseVerbose("propertyFloat=" + propertyFloat, 4);
                                break;

                            case PropType.Point3Prop:
                                IPoint3 propertyPoint3 = Loader.Global.Point3.Create(0, 0, 0);
                                RaiseVerbose("prop.GetPropertyValue(ref propertyPoint3, 0)=" + prop.GetPropertyValue(propertyPoint3, 0), 4);
                                RaiseVerbose("propertyPoint3=" + Point3ToString(propertyPoint3), 4);
                                break;

                            case PropType.Point4Prop:
                                IPoint4 propertyPoint4 = Loader.Global.Point4.Create(0, 0, 0, 0);
                                RaiseVerbose("prop.GetPropertyValue(ref propertyPoint4, 0)=" + prop.GetPropertyValue(propertyPoint4, 0), 4);
                                RaiseVerbose("propertyPoint4=" + Point4ToString(propertyPoint4), 4);
                                break;

                            case PropType.UnknownProp:
                            default:
                                RaiseVerbose("Unknown property type", 4);
                                break;
                            }
                        }
                        else
                        {
                            RaiseVerbose("propertyContainer.GetProperty(" + i + ") IS NULL", 3);
                        }
                    }
                }
            }
            #endregion

            if (materialNode.SubMaterialCount > 0)
            {
                var babylonMultimaterial = new BabylonMultiMaterial {
                    name = name, id = id
                };

                var guids = new List <string>();

                for (var index = 0; index < materialNode.SubMaterialCount; index++)
                {
                    var subMat = materialNode.GetSubMaterial(index);

                    if (subMat != null)
                    {
                        guids.Add(subMat.MaxMaterial.GetGuid().ToString());

                        if (!referencedMaterials.Contains(subMat))
                        {
                            referencedMaterials.Add(subMat);
                            ExportMaterial(subMat, babylonScene);
                        }
                    }
                    else
                    {
                        guids.Add(Guid.Empty.ToString());
                    }
                }

                babylonMultimaterial.materials = guids.ToArray();

                babylonScene.MultiMaterialsList.Add(babylonMultimaterial);
                return;
            }

            var stdMat = materialNode.MaxMaterial.GetParamBlock(0).Owner as IStdMat2;

            if (stdMat != null)
            {
                var isSelfIllumColor = materialNode.MaxMaterial.GetSelfIllumColorOn(0, false);

                var babylonMaterial = new BabylonStandardMaterial
                {
                    name          = name,
                    id            = id,
                    ambient       = materialNode.MaxMaterial.GetAmbient(0, false).ToArray(),
                    diffuse       = materialNode.MaxMaterial.GetDiffuse(0, false).ToArray(),
                    specular      = materialNode.MaxMaterial.GetSpecular(0, false).Scale(materialNode.MaxMaterial.GetShinStr(0, false)),
                    specularPower = materialNode.MaxMaterial.GetShininess(0, false) * 256,
                    emissive      =
                        isSelfIllumColor
                            ? materialNode.MaxMaterial.GetSelfIllumColor(0, false).ToArray()
                            : materialNode.MaxMaterial.GetDiffuse(0, false).Scale(materialNode.MaxMaterial.GetSelfIllum(0, false)), // compute the pre-multiplied emissive color
                    alpha = 1.0f - materialNode.MaxMaterial.GetXParency(0, false)
                };

                // If Self-Illumination color checkbox is checked
                // Then self-illumination is assumed to be pre-multiplied
                // Otherwise self-illumination needs to be multiplied with diffuse
                // linkEmissiveWithDiffuse attribute tells the Babylon engine to perform such multiplication
                babylonMaterial.linkEmissiveWithDiffuse = !isSelfIllumColor;
                // useEmissiveAsIllumination attribute tells the Babylon engine to use pre-multiplied emissive as illumination
                babylonMaterial.useEmissiveAsIllumination = isSelfIllumColor;

                // Store the emissive value (before multiplication) for gltf
                babylonMaterial.selfIllum = materialNode.MaxMaterial.GetSelfIllum(0, false);

                babylonMaterial.backFaceCulling = !stdMat.TwoSided;
                babylonMaterial.wireframe       = stdMat.Wire;

                // Textures
                BabylonFresnelParameters fresnelParameters;

                babylonMaterial.ambientTexture = ExportTexture(stdMat, 0, out fresnelParameters, babylonScene);                // Ambient
                babylonMaterial.diffuseTexture = ExportTexture(stdMat, 1, out fresnelParameters, babylonScene);                // Diffuse
                if (fresnelParameters != null)
                {
                    babylonMaterial.diffuseFresnelParameters = fresnelParameters;
                }

                babylonMaterial.specularTexture = ExportTexture(stdMat, 2, out fresnelParameters, babylonScene);               // Specular
                babylonMaterial.emissiveTexture = ExportTexture(stdMat, 5, out fresnelParameters, babylonScene);               // Emissive
                if (fresnelParameters != null)
                {
                    babylonMaterial.emissiveFresnelParameters = fresnelParameters;
                    if (babylonMaterial.emissive[0] == 0 &&
                        babylonMaterial.emissive[1] == 0 &&
                        babylonMaterial.emissive[2] == 0 &&
                        babylonMaterial.emissiveTexture == null)
                    {
                        babylonMaterial.emissive = new float[] { 1, 1, 1 };
                    }
                }

                babylonMaterial.opacityTexture = ExportTexture(stdMat, 6, out fresnelParameters, babylonScene, false, true);   // Opacity
                if (fresnelParameters != null)
                {
                    babylonMaterial.opacityFresnelParameters = fresnelParameters;
                    if (babylonMaterial.alpha == 1 &&
                        babylonMaterial.opacityTexture == null)
                    {
                        babylonMaterial.alpha = 0;
                    }
                }

                babylonMaterial.bumpTexture       = ExportTexture(stdMat, 8, out fresnelParameters, babylonScene);             // Bump
                babylonMaterial.reflectionTexture = ExportTexture(stdMat, 9, out fresnelParameters, babylonScene, true);       // Reflection
                if (fresnelParameters != null)
                {
                    if (babylonMaterial.reflectionTexture == null)
                    {
                        RaiseWarning("Fallout cannot be used with reflection channel without a texture", 2);
                    }
                    else
                    {
                        babylonMaterial.reflectionFresnelParameters = fresnelParameters;
                    }
                }

                // Constraints
                if (babylonMaterial.diffuseTexture != null)
                {
                    babylonMaterial.diffuse = new[] { 1.0f, 1.0f, 1.0f };
                }

                if (babylonMaterial.emissiveTexture != null)
                {
                    babylonMaterial.emissive = new float[] { 0, 0, 0 };
                }

                if (babylonMaterial.opacityTexture != null && babylonMaterial.diffuseTexture != null &&
                    babylonMaterial.diffuseTexture.name == babylonMaterial.opacityTexture.name &&
                    babylonMaterial.diffuseTexture.hasAlpha && !babylonMaterial.opacityTexture.getAlphaFromRGB)
                {
                    // This is a alpha testing purpose
                    babylonMaterial.opacityTexture          = null;
                    babylonMaterial.diffuseTexture.hasAlpha = true;
                    RaiseWarning("Opacity texture was removed because alpha from diffuse texture can be use instead", 2);
                    RaiseWarning("If you do not want this behavior, just set Alpha Source = None on your diffuse texture", 2);
                }

                babylonScene.MaterialsList.Add(babylonMaterial);
            }
            // TODO - Find another way to detect if material is physical
            else if (materialNode.MaterialClass.ToLower() == "physical material" ||   // English
                     materialNode.MaterialClass.ToLower() == "physisches material" || // German // TODO - check if translation is ok
                     materialNode.MaterialClass.ToLower() == "matériau physique")     // French
            {
                var propertyContainer = materialNode.IPropertyContainer;

                var babylonMaterial = new BabylonPBRMetallicRoughnessMaterial
                {
                    name = name,
                    id   = id
                };

                // --- Global ---

                // Alpha
                //var alphaFromXParency = 1.0f - materialNode.MaxMaterial.GetXParency(0, false);
                var alphaFromPropertyContainer = 1.0f - propertyContainer.GetFloatProperty(17);
                //RaiseMessage("alphaFromXParency=" + alphaFromXParency, 2);
                //RaiseMessage("alphaFromPropertyContainer=" + alphaFromPropertyContainer, 2);
                babylonMaterial.alpha = alphaFromPropertyContainer;

                babylonMaterial.baseColor = materialNode.MaxMaterial.GetDiffuse(0, false).ToArray();

                babylonMaterial.metallic = propertyContainer.GetFloatProperty(6);

                babylonMaterial.roughness = propertyContainer.GetFloatProperty(4);
                var invertRoughness = propertyContainer.GetBoolProperty(5);
                if (invertRoughness)
                {
                    // Inverse roughness
                    babylonMaterial.roughness = 1 - babylonMaterial.roughness;
                }

                // Self illumination is computed from emission color, luminance, temperature and weight
                babylonMaterial.emissive = materialNode.MaxMaterial.GetSelfIllumColorOn(0, false)
                                                ? materialNode.MaxMaterial.GetSelfIllumColor(0, false).ToArray()
                                                : materialNode.MaxMaterial.GetDiffuse(0, false).Scale(materialNode.MaxMaterial.GetSelfIllum(0, false));

                // --- Textures ---

                babylonMaterial.baseTexture = ExportBaseColorAlphaTexture(materialNode, babylonMaterial.baseColor, babylonMaterial.alpha, babylonScene, name);

                babylonMaterial.metallicRoughnessTexture = ExportMetallicRoughnessTexture(materialNode, babylonMaterial.metallic, babylonMaterial.roughness, babylonScene, name, invertRoughness);

                var normalMapAmount = propertyContainer.GetFloatProperty(91);
                babylonMaterial.normalTexture = ExportPBRTexture(materialNode, 30, babylonScene, normalMapAmount);

                babylonMaterial.emissiveTexture = ExportPBRTexture(materialNode, 17, babylonScene);

                // Use diffuse roughness map as ambient occlusion
                babylonMaterial.occlusionTexture = ExportPBRTexture(materialNode, 6, babylonScene);

                // Constraints
                if (babylonMaterial.baseTexture != null)
                {
                    babylonMaterial.baseColor = new[] { 1.0f, 1.0f, 1.0f };
                    babylonMaterial.alpha     = 1.0f;
                }

                if (babylonMaterial.alpha != 1.0f || (babylonMaterial.baseTexture != null && babylonMaterial.baseTexture.hasAlpha))
                {
                    babylonMaterial.transparencyMode = (int)BabylonPBRMetallicRoughnessMaterial.TransparencyMode.ALPHABLEND;
                }

                if (babylonMaterial.emissiveTexture != null)
                {
                    babylonMaterial.emissive = new[] { 1.0f, 1.0f, 1.0f };
                }

                if (babylonMaterial.metallicRoughnessTexture != null)
                {
                    babylonMaterial.metallic  = 1.0f;
                    babylonMaterial.roughness = 1.0f;
                }

                babylonScene.MaterialsList.Add(babylonMaterial);
            }
            else
            {
                RaiseWarning("Unsupported material type: " + materialNode.MaterialClass, 2);
            }
        }
        private void ConvertUnityMeshToBabylon(Mesh mesh, Transform transform, GameObject gameObject, float progress)
        {
            BabylonMesh babylonMesh = new BabylonMesh();
            var         renderer    = gameObject.GetComponent <Renderer>();

            ExporterWindow.ReportProgress(progress, "Exporting mesh: " + gameObject.name);

            babylonMesh.name = gameObject.name;
            babylonMesh.id   = GetID(transform.gameObject);

            if (renderer != null)
            {
                babylonMesh.receiveShadows = renderer.receiveShadows;
            }

            babylonMesh.parentId = GetParentID(transform);

            babylonMesh.position = transform.localPosition.ToFloat();

            babylonMesh.rotation    = new float[3];
            babylonMesh.rotation[0] = transform.localRotation.eulerAngles.x * (float)Math.PI / 180;
            babylonMesh.rotation[1] = transform.localRotation.eulerAngles.y * (float)Math.PI / 180;
            babylonMesh.rotation[2] = transform.localRotation.eulerAngles.z * (float)Math.PI / 180;

            babylonMesh.scaling = transform.localScale.ToFloat();

            if (mesh != null)
            {
                babylonMesh.positions = new float[mesh.vertexCount * 3];

                for (int i = 0; i < mesh.vertices.Length; i++)
                {
                    babylonMesh.positions[i * 3]       = mesh.vertices[i].x;
                    babylonMesh.positions[(i * 3) + 1] = mesh.vertices[i].y;
                    babylonMesh.positions[(i * 3) + 2] = mesh.vertices[i].z;

                    // Computing world extends
                    var worldPosition = transform.TransformPoint(mesh.vertices[i]);

                    if (worldPosition.x > babylonScene.MaxVector.X)
                    {
                        babylonScene.MaxVector.X = worldPosition.x;
                    }
                    if (worldPosition.y > babylonScene.MaxVector.Y)
                    {
                        babylonScene.MaxVector.Y = worldPosition.y;
                    }
                    if (worldPosition.z > babylonScene.MaxVector.Z)
                    {
                        babylonScene.MaxVector.Z = worldPosition.z;
                    }

                    if (worldPosition.x < babylonScene.MinVector.X)
                    {
                        babylonScene.MinVector.X = worldPosition.x;
                    }
                    if (worldPosition.y < babylonScene.MinVector.Y)
                    {
                        babylonScene.MinVector.Y = worldPosition.y;
                    }
                    if (worldPosition.z < babylonScene.MinVector.Z)
                    {
                        babylonScene.MinVector.Z = worldPosition.z;
                    }
                }

                babylonMesh.normals = new float[mesh.vertexCount * 3];

                for (int i = 0; i < mesh.normals.Length; i++)
                {
                    babylonMesh.normals[i * 3]       = mesh.normals[i].x;
                    babylonMesh.normals[(i * 3) + 1] = mesh.normals[i].y;
                    babylonMesh.normals[(i * 3) + 2] = mesh.normals[i].z;
                }

                babylonMesh.uvs = new float[mesh.vertexCount * 2];

                for (int i = 0; i < mesh.uv.Length; i++)
                {
                    babylonMesh.uvs[i * 2]       = mesh.uv[i].x;
                    babylonMesh.uvs[(i * 2) + 1] = mesh.uv[i].y;
                }

                babylonMesh.uvs2 = new float[mesh.vertexCount * 2];

                if (mesh.uv2 != null && mesh.uv2.Length > 0)
                {
                    for (int i = 0; i < mesh.uv2.Length; i++)
                    {
                        babylonMesh.uvs2[i * 2]       = mesh.uv2[i].x;
                        babylonMesh.uvs2[(i * 2) + 1] = mesh.uv2[i].y;
                    }
                }
                else
                {
                    for (int i = 0; i < mesh.uv.Length; i++)
                    {
                        babylonMesh.uvs2[i * 2]       = mesh.uv[i].x;
                        babylonMesh.uvs2[(i * 2) + 1] = mesh.uv[i].y;
                    }
                }

                babylonMesh.indices = new int[mesh.triangles.Length];

                for (int i = 0; i < mesh.triangles.Length; i += 3)
                {
                    babylonMesh.indices[i]     = mesh.triangles[i + 2];
                    babylonMesh.indices[i + 1] = mesh.triangles[i + 1];
                    babylonMesh.indices[i + 2] = mesh.triangles[i];
                }

                if (renderer != null && renderer.sharedMaterial != null)
                {
                    if (mesh.subMeshCount > 1) // Multimaterials
                    {
                        BabylonMultiMaterial bMultiMat;
                        if (!multiMatDictionary.ContainsKey(renderer.sharedMaterial.name))
                        {
                            bMultiMat = new BabylonMultiMaterial
                            {
                                materials = new string[mesh.subMeshCount],
                                id        = Guid.NewGuid().ToString(),
                                name      = renderer.sharedMaterial.name
                            };

                            for (int i = 0; i < renderer.sharedMaterials.Length; i++)
                            {
                                var             sharedMaterial = renderer.sharedMaterials[i];
                                BabylonMaterial babylonMaterial;

                                babylonMaterial = DumpMaterial(sharedMaterial, renderer);

                                bMultiMat.materials[i] = babylonMaterial.id;
                            }
                            if (mesh.subMeshCount > 1)
                            {
                                multiMatDictionary.Add(bMultiMat.name, bMultiMat);
                            }
                        }
                        else
                        {
                            bMultiMat = multiMatDictionary[renderer.sharedMaterial.name];
                        }

                        babylonMesh.materialId = bMultiMat.id;
                        babylonMesh.subMeshes  = new BabylonSubMesh[mesh.subMeshCount];

                        var offset = 0;
                        for (int materialIndex = 0; materialIndex < mesh.subMeshCount; materialIndex++)
                        {
                            var unityTriangles = mesh.GetTriangles(materialIndex);

                            babylonMesh.subMeshes[materialIndex] = new BabylonSubMesh
                            {
                                verticesStart = 0,
                                verticesCount = mesh.vertexCount,
                                materialIndex = materialIndex,
                                indexStart    = offset,
                                indexCount    = unityTriangles.Length
                            };

                            offset += unityTriangles.Length;
                        }
                    }
                    else
                    {
                        babylonMesh.materialId = DumpMaterial(renderer.sharedMaterial, renderer).id;
                    }
                }

                babylonScene.MeshesList.Add(babylonMesh);

                // Animations
                ExportAnimations(transform, babylonMesh);

                if (IsRotationQuaternionAnimated(babylonMesh))
                {
                    babylonMesh.rotationQuaternion = transform.localRotation.ToFloat();
                }

                // Collisions
                if (exportationOptions.ExportCollisions)
                {
                    var collider = gameObject.GetComponent <Collider>();

                    if (collider != null)
                    {
                        babylonMesh.checkCollisions = true;
                    }
                }
            }
        }
        private BabylonMesh ConvertUnityMeshToBabylon(Mesh mesh, Transform transform, GameObject gameObject, float progress, ref UnityMetaData metaData, ref List <BabylonExport.Entities.BabylonParticleSystem> particleSystems, ref List <UnityFlareSystem> lensFlares, ref string componentTags, BabylonMesh collisionMesh = null, Collider collider = null)
        {
            BabylonMesh babylonMesh = new BabylonMesh();

            metaData.type = "Mesh";
            if (!String.IsNullOrEmpty(componentTags))
            {
                babylonMesh.tags = componentTags;
            }

            ExporterWindow.ReportProgress(progress, "Exporting mesh: " + gameObject.name);

            babylonMesh.name = gameObject.name;
            babylonMesh.id   = GetID(transform.gameObject);

            var renderer = gameObject.GetComponent <Renderer>();

            if (renderer != null)
            {
                babylonMesh.receiveShadows = renderer.receiveShadows;
            }

            babylonMesh.parentId = GetParentID(transform);

            babylonMesh.position = transform.localPosition.ToFloat();

            babylonMesh.rotation    = new float[3];
            babylonMesh.rotation[0] = transform.localRotation.eulerAngles.x * (float)Math.PI / 180;
            babylonMesh.rotation[1] = transform.localRotation.eulerAngles.y * (float)Math.PI / 180;
            babylonMesh.rotation[2] = transform.localRotation.eulerAngles.z * (float)Math.PI / 180;

            babylonMesh.scaling         = transform.localScale.ToFloat();
            babylonMesh.checkCollisions = false;

            // Collision mesh (With detail mesh fallback)
            string collisionMeshId = null;

            if (collider != null)
            {
                if (collisionMesh != null)
                {
                    collisionMeshId               = collisionMesh.id;
                    collisionMesh.parentId        = babylonMesh.id;
                    collisionMesh.visibility      = collider.isTrigger ? 0.25f : 0.5f;
                    collisionMesh.checkCollisions = (exportationOptions.ExportCollisions && collider.isTrigger == false);
                }
                else
                {
                    babylonMesh.checkCollisions = exportationOptions.ExportCollisions;
                }
            }
            metaData.properties["collisionMeshId"] = collisionMeshId;

            if (mesh != null)
            {
                Tools.GenerateBabylonMeshData(mesh, babylonMesh, babylonScene, transform);
                int index = 0;
                if (mesh.boneWeights.Length == mesh.vertexCount)
                {
                    babylonMesh.matricesIndices = new int[mesh.vertexCount];
                    babylonMesh.matricesWeights = new float[mesh.vertexCount * 4];
                    index = 0;
                    foreach (BoneWeight bw in mesh.boneWeights)
                    {
                        babylonMesh.matricesIndices[index]         = (bw.boneIndex3 << 24) | (bw.boneIndex2 << 16) | (bw.boneIndex1 << 8) | bw.boneIndex0;
                        babylonMesh.matricesWeights[index * 4 + 0] = bw.weight0;
                        babylonMesh.matricesWeights[index * 4 + 1] = bw.weight1;
                        babylonMesh.matricesWeights[index * 4 + 2] = bw.weight2;
                        babylonMesh.matricesWeights[index * 4 + 3] = bw.weight3;
                        var totalWeight = bw.weight0 + bw.weight1 + bw.weight2 + bw.weight3;
                        if (Mathf.Abs(totalWeight - 1.0f) > 0.01f)
                        {
                            throw new Exception("Total bone weights is not normalized for: " + mesh);
                        }
                        index++;
                    }
                }
                index = 0;
                if (renderer != null && renderer.sharedMaterial != null)
                {
                    // Validate Multi Materials
                    if (mesh.subMeshCount > 1)
                    {
                        BabylonMultiMaterial bMultiMat;

                        string multiMatName = "";
                        for (int i = 0; i < renderer.sharedMaterials.Length; i++)
                        {
                            multiMatName += renderer.sharedMaterials[i].name;
                        }


                        if (!multiMatDictionary.ContainsKey(multiMatName))
                        {
                            bMultiMat = new BabylonMultiMaterial
                            {
                                materials = new string[mesh.subMeshCount],
                                id        = Guid.NewGuid().ToString(),
                                name      = multiMatName
                            };

                            for (int i = 0; i < renderer.sharedMaterials.Length; i++)
                            {
                                var             sharedMaterial = renderer.sharedMaterials[i];
                                BabylonMaterial babylonMaterial;

                                babylonMaterial = DumpMaterial(sharedMaterial, renderer.lightmapIndex, renderer.lightmapScaleOffset);

                                bMultiMat.materials[i] = babylonMaterial.id;
                            }
                            if (mesh.subMeshCount > 1)
                            {
                                multiMatDictionary.Add(bMultiMat.name, bMultiMat);
                            }
                        }
                        else
                        {
                            bMultiMat = multiMatDictionary[multiMatName];
                        }

                        babylonMesh.materialId = bMultiMat.id;
                        babylonMesh.subMeshes  = new BabylonSubMesh[mesh.subMeshCount];

                        var offset = 0;
                        for (int materialIndex = 0; materialIndex < mesh.subMeshCount; materialIndex++)
                        {
                            var unityTriangles = mesh.GetTriangles(materialIndex);
                            babylonMesh.subMeshes[materialIndex] = new BabylonSubMesh
                            {
                                verticesStart = 0,
                                verticesCount = mesh.vertexCount,
                                materialIndex = materialIndex,
                                indexStart    = offset,
                                indexCount    = unityTriangles.Length
                            };
                            offset += unityTriangles.Length;
                        }
                    }
                    else
                    {
                        babylonMesh.materialId = DumpMaterial(renderer.sharedMaterial, renderer.lightmapIndex, renderer.lightmapScaleOffset).id;
                    }
                }

                babylonMesh.metadata = metaData;
                babylonScene.MeshesList.Add(babylonMesh);

                // Animations
                ExportAnimations(transform, babylonMesh);
                if (IsRotationQuaternionAnimated(babylonMesh))
                {
                    babylonMesh.rotationQuaternion = transform.localRotation.ToFloat();
                }

                // Lens Flares
                ParseLensFlares(gameObject, babylonMesh.id, ref lensFlares);

                // Particles Systems
                ParseParticleSystems(gameObject, babylonMesh.id, ref particleSystems);

                // Babylon Physics
                if (exportationOptions.ExportPhysics)
                {
                    var physics = gameObject.GetComponent <BabylonPhysicsState>();
                    if (physics != null)
                    {
                        babylonMesh.physicsMass        = physics.mass;
                        babylonMesh.physicsFriction    = physics.friction;
                        babylonMesh.physicsRestitution = physics.restitution;
                        babylonMesh.physicsImpostor    = (int)physics.imposter;
                    }
                }
            }
            return(babylonMesh);
        }
        private void ExportMaterial(IIGameMaterial materialNode, BabylonScene babylonScene)
        {
            var name = materialNode.MaterialName;
            var id   = materialNode.MaxMaterial.GetGuid().ToString();

            // Check if the material was already exported. The material id is unique.
            if (babylonScene.MaterialsList.FirstOrDefault(m => m.id == id) != null)
            {
                return;
            }

            RaiseMessage(name, 1);

            // --- prints ---
            #region prints
            {
                RaiseVerbose("materialNode.MaterialClass=" + materialNode.MaterialClass, 2);
                RaiseVerbose("materialNode.NumberOfTextureMaps=" + materialNode.NumberOfTextureMaps, 2);

                var propertyContainer = materialNode.IPropertyContainer;
                RaiseVerbose("propertyContainer=" + propertyContainer, 2);
                if (propertyContainer != null)
                {
                    RaiseVerbose("propertyContainer.NumberOfProperties=" + propertyContainer.NumberOfProperties, 3);
                    for (int i = 0; i < propertyContainer.NumberOfProperties; i++)
                    {
                        var prop = propertyContainer.GetProperty(i);
                        if (prop != null)
                        {
                            RaiseVerbose("propertyContainer.GetProperty(" + i + ")=" + prop.Name, 3);
                            switch (prop.GetType_)
                            {
                            case PropType.StringProp:
                                string propertyString = "";
                                RaiseVerbose("prop.GetPropertyValue(ref propertyString, 0)=" + prop.GetPropertyValue(ref propertyString, 0), 4);
                                RaiseVerbose("propertyString=" + propertyString, 4);
                                break;

                            case PropType.IntProp:
                                int propertyInt = 0;
                                RaiseVerbose("prop.GetPropertyValue(ref propertyInt, 0)=" + prop.GetPropertyValue(ref propertyInt, 0), 4);
                                RaiseVerbose("propertyInt=" + propertyInt, 4);
                                break;

                            case PropType.FloatProp:
                                float propertyFloat = 0;
                                RaiseVerbose("prop.GetPropertyValue(ref propertyFloat, 0, true)=" + prop.GetPropertyValue(ref propertyFloat, 0, true), 4);
                                RaiseVerbose("propertyFloat=" + propertyFloat, 4);
                                RaiseVerbose("prop.GetPropertyValue(ref propertyFloat, 0, false)=" + prop.GetPropertyValue(ref propertyFloat, 0, false), 4);
                                RaiseVerbose("propertyFloat=" + propertyFloat, 4);
                                break;

                            case PropType.Point3Prop:
                                IPoint3 propertyPoint3 = Loader.Global.Point3.Create(0, 0, 0);
                                RaiseVerbose("prop.GetPropertyValue(ref propertyPoint3, 0)=" + prop.GetPropertyValue(propertyPoint3, 0), 4);
                                RaiseVerbose("propertyPoint3=" + Point3ToString(propertyPoint3), 4);
                                break;

                            case PropType.Point4Prop:
                                IPoint4 propertyPoint4 = Loader.Global.Point4.Create(0, 0, 0, 0);
                                RaiseVerbose("prop.GetPropertyValue(ref propertyPoint4, 0)=" + prop.GetPropertyValue(propertyPoint4, 0), 4);
                                RaiseVerbose("propertyPoint4=" + Point4ToString(propertyPoint4), 4);
                                break;

                            case PropType.UnknownProp:
                            default:
                                RaiseVerbose("Unknown property type", 4);
                                break;
                            }
                        }
                        else
                        {
                            RaiseVerbose("propertyContainer.GetProperty(" + i + ") IS NULL", 3);
                        }
                    }
                }
            }
            #endregion

            if (materialNode.SubMaterialCount > 0)
            {
                var babylonMultimaterial = new BabylonMultiMaterial {
                    name = name, id = id
                };

                var guids = new List <string>();

                for (var index = 0; index < materialNode.SubMaterialCount; index++)
                {
                    var subMat = materialNode.GetSubMaterial(index);

                    if (subMat != null)
                    {
                        guids.Add(subMat.MaxMaterial.GetGuid().ToString());

                        if (!referencedMaterials.Contains(subMat))
                        {
                            referencedMaterials.Add(subMat);
                            ExportMaterial(subMat, babylonScene);
                        }
                    }
                    else
                    {
                        guids.Add(Guid.Empty.ToString());
                    }
                }

                babylonMultimaterial.materials = guids.ToArray();

                babylonScene.MultiMaterialsList.Add(babylonMultimaterial);
                return;
            }

            var  unlitProperty = materialNode.IPropertyContainer.QueryProperty("BabylonUnlit");
            bool isUnlit       = unlitProperty != null?unlitProperty.GetBoolValue() : false;


            var stdMat = materialNode.MaxMaterial.NumParamBlocks > 0 ? materialNode.MaxMaterial.GetParamBlock(0).Owner as IStdMat2 : null;

            if (stdMat != null)
            {
                var babylonMaterial = new BabylonStandardMaterial
                {
                    name    = name,
                    id      = id,
                    isUnlit = isUnlit,
                    diffuse = materialNode.MaxMaterial.GetDiffuse(0, false).ToArray(),
                    alpha   = 1.0f - materialNode.MaxMaterial.GetXParency(0, false)
                };

                babylonMaterial.backFaceCulling = !stdMat.TwoSided;
                babylonMaterial.wireframe       = stdMat.Wire;

                var isSelfIllumColor = materialNode.MaxMaterial.GetSelfIllumColorOn(0, false);
                var maxSpecularColor = materialNode.MaxMaterial.GetSpecular(0, false).ToArray();

                if (isUnlit == false)
                {
                    babylonMaterial.ambient       = materialNode.MaxMaterial.GetAmbient(0, false).ToArray();
                    babylonMaterial.specular      = maxSpecularColor.Multiply(materialNode.MaxMaterial.GetShinStr(0, false));
                    babylonMaterial.specularPower = materialNode.MaxMaterial.GetShininess(0, false) * 256;
                    babylonMaterial.emissive      =
                        isSelfIllumColor
                            ? materialNode.MaxMaterial.GetSelfIllumColor(0, false).ToArray()
                            : materialNode.MaxMaterial.GetDiffuse(0, false).Scale(materialNode.MaxMaterial.GetSelfIllum(0, false)); // compute the pre-multiplied emissive color

                    // If Self-Illumination color checkbox is checked
                    // Then self-illumination is assumed to be pre-multiplied
                    // Otherwise self-illumination needs to be multiplied with diffuse
                    // linkEmissiveWithDiffuse attribute tells the Babylon engine to perform such multiplication
                    babylonMaterial.linkEmissiveWithDiffuse = !isSelfIllumColor;
                    // useEmissiveAsIllumination attribute tells the Babylon engine to use pre-multiplied emissive as illumination
                    babylonMaterial.useEmissiveAsIllumination = isSelfIllumColor;

                    // Store the emissive value (before multiplication) for gltf
                    babylonMaterial.selfIllum = materialNode.MaxMaterial.GetSelfIllum(0, false);
                }

                // Textures

                BabylonFresnelParameters fresnelParameters;
                babylonMaterial.diffuseTexture = ExportTexture(stdMat, 1, out fresnelParameters, babylonScene);                // Diffuse
                if (fresnelParameters != null)
                {
                    babylonMaterial.diffuseFresnelParameters = fresnelParameters;
                }
                if ((babylonMaterial.alpha == 1.0f && babylonMaterial.opacityTexture == null) &&
                    babylonMaterial.diffuseTexture != null &&
                    (babylonMaterial.diffuseTexture.originalPath.EndsWith(".tif") || babylonMaterial.diffuseTexture.originalPath.EndsWith(".tiff")) &&
                    babylonMaterial.diffuseTexture.hasAlpha)
                {
                    RaiseWarning($"Diffuse texture named {babylonMaterial.diffuseTexture.originalPath} is a .tif file and its Alpha Source is 'Image Alpha' by default.", 2);
                    RaiseWarning($"If you don't want material to be in BLEND mode, set diffuse texture Alpha Source to 'None (Opaque)'", 2);
                }

                babylonMaterial.opacityTexture = ExportTexture(stdMat, 6, out fresnelParameters, babylonScene, false, true);   // Opacity
                if (fresnelParameters != null)
                {
                    babylonMaterial.opacityFresnelParameters = fresnelParameters;
                    if (babylonMaterial.alpha == 1 &&
                        babylonMaterial.opacityTexture == null)
                    {
                        babylonMaterial.alpha = 0;
                    }
                }

                if (isUnlit == false)
                {
                    babylonMaterial.ambientTexture = ExportTexture(stdMat, 0, out fresnelParameters, babylonScene);                // Ambient

                    babylonMaterial.specularTexture = ExportSpecularTexture(materialNode, maxSpecularColor, babylonScene);

                    babylonMaterial.emissiveTexture = ExportTexture(stdMat, 5, out fresnelParameters, babylonScene);               // Emissive
                    if (fresnelParameters != null)
                    {
                        babylonMaterial.emissiveFresnelParameters = fresnelParameters;
                        if (babylonMaterial.emissive[0] == 0 &&
                            babylonMaterial.emissive[1] == 0 &&
                            babylonMaterial.emissive[2] == 0 &&
                            babylonMaterial.emissiveTexture == null)
                        {
                            babylonMaterial.emissive = new float[] { 1, 1, 1 };
                        }
                    }

                    babylonMaterial.bumpTexture       = ExportTexture(stdMat, 8, out fresnelParameters, babylonScene);             // Bump
                    babylonMaterial.reflectionTexture = ExportTexture(stdMat, 9, out fresnelParameters, babylonScene, true);       // Reflection
                    if (fresnelParameters != null)
                    {
                        if (babylonMaterial.reflectionTexture == null)
                        {
                            RaiseWarning("Fallout cannot be used with reflection channel without a texture", 2);
                        }
                        else
                        {
                            babylonMaterial.reflectionFresnelParameters = fresnelParameters;
                        }
                    }
                }

                // Constraints
                if (babylonMaterial.diffuseTexture != null)
                {
                    babylonMaterial.diffuse = new[] { 1.0f, 1.0f, 1.0f };
                }

                if (babylonMaterial.emissiveTexture != null)
                {
                    babylonMaterial.emissive = new float[] { 0, 0, 0 };
                }

                if (babylonMaterial.opacityTexture != null && babylonMaterial.diffuseTexture != null &&
                    babylonMaterial.diffuseTexture.name == babylonMaterial.opacityTexture.name &&
                    babylonMaterial.diffuseTexture.hasAlpha && !babylonMaterial.opacityTexture.getAlphaFromRGB)
                {
                    // This is a alpha testing purpose
                    babylonMaterial.opacityTexture          = null;
                    babylonMaterial.diffuseTexture.hasAlpha = true;
                    RaiseWarning("Opacity texture was removed because alpha from diffuse texture can be use instead", 2);
                    RaiseWarning("If you do not want this behavior, just set Alpha Source = None on your diffuse texture", 2);
                }

                babylonScene.MaterialsList.Add(babylonMaterial);
            }
            else if (isPhysicalMaterial(materialNode))
            {
                var propertyContainer = materialNode.IPropertyContainer;

                var babylonMaterial = new BabylonPBRMetallicRoughnessMaterial
                {
                    name    = name,
                    id      = id,
                    isUnlit = isUnlit
                };

                // --- Global ---

                // Alpha
                //var alphaFromXParency = 1.0f - materialNode.MaxMaterial.GetXParency(0, false);
                var alphaFromPropertyContainer = 1.0f - propertyContainer.GetFloatProperty(17);
                //RaiseMessage("alphaFromXParency=" + alphaFromXParency, 2);
                //RaiseMessage("alphaFromPropertyContainer=" + alphaFromPropertyContainer, 2);
                babylonMaterial.alpha = alphaFromPropertyContainer;

                babylonMaterial.baseColor = materialNode.MaxMaterial.GetDiffuse(0, false).ToArray();

                var invertRoughness = propertyContainer.GetBoolProperty(5);
                if (isUnlit == false)
                {
                    babylonMaterial.metallic = propertyContainer.GetFloatProperty(6);

                    babylonMaterial.roughness = propertyContainer.GetFloatProperty(4);
                    if (invertRoughness)
                    {
                        // Inverse roughness
                        babylonMaterial.roughness = 1 - babylonMaterial.roughness;
                    }

                    // Self illumination is computed from emission color, luminance, temperature and weight
                    babylonMaterial.emissive = materialNode.MaxMaterial.GetSelfIllumColorOn(0, false)
                                                    ? materialNode.MaxMaterial.GetSelfIllumColor(0, false).ToArray()
                                                    : materialNode.MaxMaterial.GetDiffuse(0, false).Scale(materialNode.MaxMaterial.GetSelfIllum(0, false));
                }
                else
                {
                    // Ignore specified roughness and metallic values
                    babylonMaterial.metallic  = 0;
                    babylonMaterial.roughness = 0.9f;
                }

                // --- Textures ---
                // 1 - base color ; 9 - transparancy weight
                ITexmap colorTexmap = _getTexMap(materialNode, 1);
                ITexmap alphaTexmap = _getTexMap(materialNode, 9);
                babylonMaterial.baseTexture = ExportBaseColorAlphaTexture(colorTexmap, alphaTexmap, babylonMaterial.baseColor, babylonMaterial.alpha, babylonScene, name);

                if (isUnlit == false)
                {
                    // Metallic, roughness, ambient occlusion
                    ITexmap metallicTexmap         = _getTexMap(materialNode, 5);
                    ITexmap roughnessTexmap        = _getTexMap(materialNode, 4);
                    ITexmap ambientOcclusionTexmap = _getTexMap(materialNode, 6); // Use diffuse roughness map as ambient occlusion

                    // Check if MR or ORM textures are already merged
                    bool areTexturesAlreadyMerged = false;
                    if (metallicTexmap != null && roughnessTexmap != null)
                    {
                        string sourcePathMetallic  = getSourcePath(metallicTexmap);
                        string sourcePathRoughness = getSourcePath(roughnessTexmap);

                        if (sourcePathMetallic == sourcePathRoughness)
                        {
                            if (ambientOcclusionTexmap != null && exportParameters.mergeAOwithMR)
                            {
                                string sourcePathAmbientOcclusion = getSourcePath(ambientOcclusionTexmap);
                                if (sourcePathMetallic == sourcePathAmbientOcclusion)
                                {
                                    // Metallic, roughness and ambient occlusion are already merged
                                    RaiseVerbose("Metallic, roughness and ambient occlusion are already merged", 2);
                                    BabylonTexture ormTexture = ExportTexture(metallicTexmap, babylonScene);
                                    babylonMaterial.metallicRoughnessTexture = ormTexture;
                                    babylonMaterial.occlusionTexture         = ormTexture;
                                    areTexturesAlreadyMerged = true;
                                }
                            }
                            else
                            {
                                // Metallic and roughness are already merged
                                RaiseVerbose("Metallic and roughness are already merged", 2);
                                BabylonTexture ormTexture = ExportTexture(metallicTexmap, babylonScene);
                                babylonMaterial.metallicRoughnessTexture = ormTexture;
                                areTexturesAlreadyMerged = true;
                            }
                        }
                    }
                    if (areTexturesAlreadyMerged == false)
                    {
                        if (metallicTexmap != null || roughnessTexmap != null)
                        {
                            // Merge metallic, roughness and ambient occlusion
                            RaiseVerbose("Merge metallic and roughness (and ambient occlusion if `mergeAOwithMR` is enabled)", 2);
                            BabylonTexture ormTexture = ExportORMTexture(exportParameters.mergeAOwithMR ? ambientOcclusionTexmap : null, roughnessTexmap, metallicTexmap, babylonMaterial.metallic, babylonMaterial.roughness, babylonScene, invertRoughness);
                            babylonMaterial.metallicRoughnessTexture = ormTexture;

                            if (ambientOcclusionTexmap != null)
                            {
                                if (exportParameters.mergeAOwithMR)
                                {
                                    babylonMaterial.occlusionTexture = ormTexture;
                                }
                                else
                                {
                                    babylonMaterial.occlusionTexture = ExportPBRTexture(materialNode, 6, babylonScene);
                                }
                            }
                        }
                        else if (ambientOcclusionTexmap != null)
                        {
                            // Simply export occlusion texture
                            RaiseVerbose("Simply export occlusion texture", 2);
                            babylonMaterial.occlusionTexture = ExportTexture(ambientOcclusionTexmap, babylonScene);
                        }
                    }
                    if (ambientOcclusionTexmap != null && !exportParameters.mergeAOwithMR && babylonMaterial.occlusionTexture == null)
                    {
                        RaiseVerbose("Exporting occlusion texture without merging with metallic roughness", 2);
                        babylonMaterial.occlusionTexture = ExportTexture(ambientOcclusionTexmap, babylonScene);
                    }

                    var normalMapAmount = propertyContainer.GetFloatProperty(91);
                    babylonMaterial.normalTexture = ExportPBRTexture(materialNode, 30, babylonScene, normalMapAmount);

                    babylonMaterial.emissiveTexture = ExportPBRTexture(materialNode, 17, babylonScene);
                }


                if (babylonMaterial.alpha != 1.0f || (babylonMaterial.baseTexture != null && babylonMaterial.baseTexture.hasAlpha))
                {
                    var  alphaTestProperty = materialNode.IPropertyContainer.QueryProperty("BabylonAlphaTest");
                    bool isAlphaTest       = alphaTestProperty != null?alphaTestProperty.GetBoolValue() : false;

                    babylonMaterial.transparencyMode = isAlphaTest ? (int)BabylonPBRMetallicRoughnessMaterial.TransparencyMode.ALPHATEST : (int)BabylonPBRMetallicRoughnessMaterial.TransparencyMode.ALPHABLEND;
                }

                if (babylonMaterial.emissiveTexture != null)
                {
                    babylonMaterial.emissive = new[] { 1.0f, 1.0f, 1.0f };
                }

                if (babylonMaterial.metallicRoughnessTexture != null)
                {
                    babylonMaterial.metallic  = 1.0f;
                    babylonMaterial.roughness = 1.0f;
                }

                babylonScene.MaterialsList.Add(babylonMaterial);
            }
            else if (isArnoldMaterial(materialNode))
            {
                var propertyContainer = materialNode.IPropertyContainer;
                var babylonMaterial   = new BabylonPBRMetallicRoughnessMaterial
                {
                    name    = name,
                    id      = id,
                    isUnlit = isUnlit
                };

                // Alpha
                babylonMaterial.alpha = 1.0f - propertyContainer.GetFloatProperty(32);

                // Color: base * weight
                float[] baseColor  = propertyContainer.GetPoint3Property(5).ToArray();
                float   baseWeight = propertyContainer.GetFloatProperty(2);
                babylonMaterial.baseColor = baseColor.Multiply(baseWeight);

                // Metallic & roughness
                bool invertRoughness = false;
                babylonMaterial.roughness = propertyContainer.GetFloatProperty(17); // specular_roughness
                babylonMaterial.metallic  = propertyContainer.GetFloatProperty(29);

                // Emissive: emission_color * emission
                float[] emissionColor  = propertyContainer.GetPoint3Property(94).ToArray();
                float   emissionWeight = propertyContainer.GetFloatProperty(91);
                babylonMaterial.emissive = emissionColor.Multiply(emissionWeight);

                // --- Textures ---
                // 1 - base_color ; 5 - diffuse_roughness ; 9 - metalness ; 10 - transparent
                ITexmap colorTexmap = _getTexMap(materialNode, 1);
                ITexmap alphaTexmap = _getTexMap(materialNode, 10);
                babylonMaterial.baseTexture = ExportBaseColorAlphaTexture(colorTexmap, alphaTexmap, babylonMaterial.baseColor, babylonMaterial.alpha, babylonScene, name);

                if (isUnlit == false)
                {
                    // Metallic, roughness
                    ITexmap metallicTexmap  = _getTexMap(materialNode, 9);
                    ITexmap roughnessTexmap = _getTexMap(materialNode, 5);

                    // Check if MR textures are already merged
                    bool areTexturesAlreadyMerged = false;
                    if (metallicTexmap != null && roughnessTexmap != null)
                    {
                        string sourcePathMetallic  = getSourcePath(metallicTexmap);
                        string sourcePathRoughness = getSourcePath(roughnessTexmap);

                        if (sourcePathMetallic == sourcePathRoughness)
                        {
                            // Metallic and roughness are already merged
                            RaiseVerbose("Metallic and roughness are already merged", 2);
                            BabylonTexture ormTexture = ExportTexture(metallicTexmap, babylonScene);
                            babylonMaterial.metallicRoughnessTexture = ormTexture;
                            // The already merged map is assumed to contain Ambient Occlusion in R channel
                            babylonMaterial.occlusionTexture = ormTexture;
                            areTexturesAlreadyMerged         = true;
                        }
                    }
                    if (areTexturesAlreadyMerged == false)
                    {
                        if (metallicTexmap != null || roughnessTexmap != null)
                        {
                            // Merge metallic, roughness
                            RaiseVerbose("Merge metallic and roughness", 2);
                            BabylonTexture ormTexture = ExportORMTexture(null, roughnessTexmap, metallicTexmap, babylonMaterial.metallic, babylonMaterial.roughness, babylonScene, invertRoughness);
                            babylonMaterial.metallicRoughnessTexture = ormTexture;
                        }
                    }

                    babylonMaterial.normalTexture   = ExportPBRTexture(materialNode, 20, babylonScene);
                    babylonMaterial.emissiveTexture = ExportPBRTexture(materialNode, 30, babylonScene);
                }

                // Constraints
                if (babylonMaterial.baseTexture != null)
                {
                    babylonMaterial.baseColor = new[] { 1.0f, 1.0f, 1.0f };
                    babylonMaterial.alpha     = 1.0f;
                }

                if (babylonMaterial.alpha != 1.0f || (babylonMaterial.baseTexture != null && babylonMaterial.baseTexture.hasAlpha))
                {
                    babylonMaterial.transparencyMode = (int)BabylonPBRMetallicRoughnessMaterial.TransparencyMode.ALPHABLEND;
                }

                if (babylonMaterial.emissiveTexture != null)
                {
                    babylonMaterial.emissive = new[] { 1.0f, 1.0f, 1.0f };
                }

                if (babylonMaterial.metallicRoughnessTexture != null)
                {
                    babylonMaterial.metallic  = 1.0f;
                    babylonMaterial.roughness = 1.0f;
                }

                // Add the material to the scene
                babylonScene.MaterialsList.Add(babylonMaterial);
            }
            else
            {
                // isMaterialExportable check should prevent this to happen
                RaiseError("Unsupported material type: " + materialNode.MaterialClass, 2);
            }
        }
Beispiel #7
0
        private void UpdateMeshesMaterialId(BabylonScene babylonScene)
        {
            // --- Update meshes using simple materials ---
            foreach (MFnDependencyNode material in referencedMaterials)
            {
                string materialId = material.uuid().asString();

                // If it's an AiStandardSurface material
                if (materialDuplicationDatas.ContainsKey(materialId))
                {
                    MaterialDuplicationData materialDuplicationValue = materialDuplicationDatas[materialId];

                    // If both Opaque and Transparent meshes are using this material
                    // And the material contains alpha data
                    if (materialDuplicationValue.idOpaque != null && materialDuplicationValue.isDuplicationSuccess)
                    {
                        // The duplicated material is used for Opaque meshes instead of the original one
                        foreach (BabylonMesh meshOpaque in materialDuplicationValue.meshesOpaque)
                        {
                            meshOpaque.materialId = materialDuplicationValue.idOpaque;
                        }
                    }
                }
            }

            // --- Update meshes using multimaterials ---
            var multiMaterialsList = new List <BabylonMultiMaterial>(babylonScene.MultiMaterialsList);

            foreach (BabylonMultiMaterial babylonMultiMaterial in multiMaterialsList)
            {
                string multiMaterialId = babylonMultiMaterial.id;

                // If at least one Opaque mesh is using this multimaterial
                if (meshesOpaqueMultis[multiMaterialId].Count > 0)
                {
                    List <MFnDependencyNode> subMaterials = multiMaterials[multiMaterialId];

                    // Build a list of all opaque sub material ids
                    List <string> opaqueSubMaterials = new List <string>();
                    foreach (MFnDependencyNode subMaterial in subMaterials)
                    {
                        string subMaterialId = subMaterial.uuid().asString();

                        // If it's an AiStandardSurface material
                        if (materialDuplicationDatas.ContainsKey(subMaterialId))
                        {
                            MaterialDuplicationData materialDuplicationValue = materialDuplicationDatas[subMaterialId];

                            // If both Opaque and Transparent meshes are using this sub material
                            // And the sub material contains alpha data
                            if (materialDuplicationValue.idOpaque != null && materialDuplicationValue.isDuplicationSuccess)
                            {
                                // The duplicated material is used for Opaque meshes instead of the original one
                                subMaterialId = materialDuplicationValue.idOpaque;
                            }
                        }

                        opaqueSubMaterials.Add(subMaterialId);
                    }

                    // If both Opaque and Transparent meshes are using this multimaterial
                    if (meshesTransparentMultis[multiMaterialId].Count > 0)
                    {
                        // Duplicate multimaterial
                        BabylonMultiMaterial multiMaterialCloned = new BabylonMultiMaterial(babylonMultiMaterial);

                        // Update id
                        string idMultiMaterialCloned = Tools.GenerateUUID();
                        multiMaterialCloned.id = idMultiMaterialCloned;

                        // Update sub materials
                        multiMaterialCloned.materials = opaqueSubMaterials.ToArray();

                        // Store duplication
                        babylonScene.MultiMaterialsList.Add(multiMaterialCloned);

                        // Update meshes id
                        foreach (BabylonMesh meshOpaque in meshesOpaqueMultis[multiMaterialId])
                        {
                            meshOpaque.materialId = idMultiMaterialCloned;
                        }
                    }
                    else
                    {
                        // Only Opaque meshes are using this multimaterial
                        // Simply override sub materials with all opaque ones
                        babylonMultiMaterial.materials = opaqueSubMaterials.ToArray();
                    }
                }
            }
        }
Beispiel #8
0
        private void ExportMaterial(IIGameMaterial materialNode, BabylonScene babylonScene)
        {
            var name = materialNode.MaterialName;
            var id   = materialNode.MaxMaterial.GetGuid().ToString();

            RaiseMessage(name, 1);

            if (materialNode.SubMaterialCount > 0)
            {
                var babylonMultimaterial = new BabylonMultiMaterial {
                    name = name, id = id
                };

                var guids = new List <string>();

                for (var index = 0; index < materialNode.SubMaterialCount; index++)
                {
                    var subMat = materialNode.GetSubMaterial(index);

                    if (subMat != null)
                    {
                        guids.Add(subMat.MaxMaterial.GetGuid().ToString());

                        if (!referencedMaterials.Contains(subMat))
                        {
                            referencedMaterials.Add(subMat);
                            ExportMaterial(subMat, babylonScene);
                        }
                    }
                    else
                    {
                        guids.Add(Guid.Empty.ToString());
                    }
                }

                babylonMultimaterial.materials = guids.ToArray();

                babylonScene.MultiMaterialsList.Add(babylonMultimaterial);
                return;
            }

            var babylonMaterial = new BabylonStandardMaterial
            {
                name          = name,
                id            = id,
                ambient       = materialNode.MaxMaterial.GetAmbient(0, false).ToArray(),
                diffuse       = materialNode.MaxMaterial.GetDiffuse(0, false).ToArray(),
                specular      = materialNode.MaxMaterial.GetSpecular(0, false).Scale(materialNode.MaxMaterial.GetShinStr(0, false)),
                specularPower = materialNode.MaxMaterial.GetShininess(0, false) * 256,
                emissive      =
                    materialNode.MaxMaterial.GetSelfIllumColorOn(0, false)
                        ? materialNode.MaxMaterial.GetSelfIllumColor(0, false).ToArray()
                        : materialNode.MaxMaterial.GetDiffuse(0, false).Scale(materialNode.MaxMaterial.GetSelfIllum(0, false)),
                alpha = 1.0f - materialNode.MaxMaterial.GetXParency(0, false)
            };


            var stdMat = materialNode.MaxMaterial.GetParamBlock(0).Owner as IStdMat2;

            if (stdMat != null)
            {
                babylonMaterial.backFaceCulling = !stdMat.TwoSided;
                babylonMaterial.wireframe       = stdMat.Wire;

                // Textures
                BabylonFresnelParameters fresnelParameters;

                babylonMaterial.ambientTexture = ExportTexture(stdMat, 0, out fresnelParameters, babylonScene);                // Ambient
                babylonMaterial.diffuseTexture = ExportTexture(stdMat, 1, out fresnelParameters, babylonScene);                // Diffuse
                if (fresnelParameters != null)
                {
                    babylonMaterial.diffuseFresnelParameters = fresnelParameters;
                }

                babylonMaterial.specularTexture = ExportTexture(stdMat, 2, out fresnelParameters, babylonScene);               // Specular
                babylonMaterial.emissiveTexture = ExportTexture(stdMat, 5, out fresnelParameters, babylonScene);               // Emissive
                if (fresnelParameters != null)
                {
                    babylonMaterial.emissiveFresnelParameters = fresnelParameters;
                    if (babylonMaterial.emissive[0] == 0 &&
                        babylonMaterial.emissive[1] == 0 &&
                        babylonMaterial.emissive[2] == 0 &&
                        babylonMaterial.emissiveTexture == null)
                    {
                        babylonMaterial.emissive = new float[] { 1, 1, 1 };
                    }
                }

                babylonMaterial.opacityTexture = ExportTexture(stdMat, 6, out fresnelParameters, babylonScene, false, true);   // Opacity
                if (fresnelParameters != null)
                {
                    babylonMaterial.opacityFresnelParameters = fresnelParameters;
                    if (babylonMaterial.alpha == 1 &&
                        babylonMaterial.opacityTexture == null)
                    {
                        babylonMaterial.alpha = 0;
                    }
                }

                babylonMaterial.bumpTexture       = ExportTexture(stdMat, 8, out fresnelParameters, babylonScene);             // Bump
                babylonMaterial.reflectionTexture = ExportTexture(stdMat, 9, out fresnelParameters, babylonScene, true);       // Reflection
                if (fresnelParameters != null)
                {
                    if (babylonMaterial.reflectionTexture == null)
                    {
                        RaiseWarning("Fallout cannot be used with reflection channel without a texture", 2);
                    }
                    else
                    {
                        babylonMaterial.reflectionFresnelParameters = fresnelParameters;
                    }
                }

                // Constraints
                if (babylonMaterial.diffuseTexture != null)
                {
                    babylonMaterial.diffuse = new[] { 1.0f, 1.0f, 1.0f };
                }

                if (babylonMaterial.emissiveTexture != null)
                {
                    babylonMaterial.emissive = new float[] { 0, 0, 0 };
                }

                if (babylonMaterial.opacityTexture != null && babylonMaterial.diffuseTexture != null &&
                    babylonMaterial.diffuseTexture.name == babylonMaterial.opacityTexture.name &&
                    babylonMaterial.diffuseTexture.hasAlpha && !babylonMaterial.opacityTexture.getAlphaFromRGB)
                {
                    // This is a alpha testing purpose
                    babylonMaterial.opacityTexture          = null;
                    babylonMaterial.diffuseTexture.hasAlpha = true;
                    RaiseWarning("Opacity texture was removed because alpha from diffuse texture can be use instead", 2);
                    RaiseWarning("If you do not want this behavior, just set Alpha Source = None on your diffuse texture", 2);
                }
            }

            babylonScene.MaterialsList.Add(babylonMaterial);
        }
        private void ExportMaterial(IIGameMaterial materialNode, BabylonScene babylonScene)
        {
            var name = materialNode.MaterialName;
            var id   = materialNode.MaxMaterial.GetGuid().ToString();

            RaiseMessage(name, 1);

            // --- prints ---
            {
                RaiseMessage("materialNode.MaterialClass=" + materialNode.MaterialClass, 2);
                RaiseMessage("materialNode.NumberOfTextureMaps=" + materialNode.NumberOfTextureMaps, 2);

                var propertyContainer = materialNode.IPropertyContainer;
                RaiseMessage("propertyContainer=" + propertyContainer, 2);
                if (propertyContainer != null)
                {
                    RaiseMessage("propertyContainer.NumberOfProperties=" + propertyContainer.NumberOfProperties, 3);
                    for (int i = 0; i < propertyContainer.NumberOfProperties; i++)
                    {
                        var prop = propertyContainer.GetProperty(i);
                        if (prop != null)
                        {
                            RaiseMessage("propertyContainer.GetProperty(" + i + ")=" + prop.Name, 3);
                            switch (prop.GetType_)
                            {
                            case PropType.StringProp:
                                string propertyString = "";
                                RaiseMessage("prop.GetPropertyValue(ref propertyString, 0)=" + prop.GetPropertyValue(ref propertyString, 0), 4);
                                RaiseMessage("propertyString=" + propertyString, 4);
                                break;

                            case PropType.IntProp:
                                int propertyInt = 0;
                                RaiseMessage("prop.GetPropertyValue(ref propertyInt, 0)=" + prop.GetPropertyValue(ref propertyInt, 0), 4);
                                RaiseMessage("propertyInt=" + propertyInt, 4);
                                break;

                            case PropType.FloatProp:
                                float propertyFloat = 0;
                                RaiseMessage("prop.GetPropertyValue(ref propertyFloat, 0)=" + prop.GetPropertyValue(ref propertyFloat, 0, true), 4);
                                RaiseMessage("propertyFloat=" + propertyFloat, 4);
                                RaiseMessage("prop.GetPropertyValue(ref propertyFloat, 0)=" + prop.GetPropertyValue(ref propertyFloat, 0, false), 4);
                                RaiseMessage("propertyFloat=" + propertyFloat, 4);
                                break;

                            case PropType.Point3Prop:
                                IPoint3 propertyPoint3 = Loader.Global.Point3.Create(0, 0, 0);
                                RaiseMessage("prop.GetPropertyValue(ref propertyPoint3, 0)=" + prop.GetPropertyValue(propertyPoint3, 0), 4);
                                RaiseMessage("propertyPoint3=" + Point3ToString(propertyPoint3), 4);
                                break;

                            case PropType.Point4Prop:
                                IPoint4 propertyPoint4 = Loader.Global.Point4.Create(0, 0, 0, 0);
                                RaiseMessage("prop.GetPropertyValue(ref propertyPoint4, 0)=" + prop.GetPropertyValue(propertyPoint4, 0), 4);
                                RaiseMessage("propertyPoint4=" + Point4ToString(propertyPoint4), 4);
                                break;

                            case PropType.UnknownProp:
                            default:
                                RaiseMessage("Unknown property type", 4);
                                break;
                            }
                        }
                        else
                        {
                            RaiseMessage("propertyContainer.GetProperty(" + i + ") IS NULL", 3);
                        }
                    }
                }
            }

            if (materialNode.SubMaterialCount > 0)
            {
                var babylonMultimaterial = new BabylonMultiMaterial {
                    name = name, id = id
                };

                var guids = new List <string>();

                for (var index = 0; index < materialNode.SubMaterialCount; index++)
                {
                    var subMat = materialNode.GetSubMaterial(index);

                    if (subMat != null)
                    {
                        guids.Add(subMat.MaxMaterial.GetGuid().ToString());

                        if (!referencedMaterials.Contains(subMat))
                        {
                            referencedMaterials.Add(subMat);
                            ExportMaterial(subMat, babylonScene);
                        }
                    }
                    else
                    {
                        guids.Add(Guid.Empty.ToString());
                    }
                }

                babylonMultimaterial.materials = guids.ToArray();

                babylonScene.MultiMaterialsList.Add(babylonMultimaterial);
                return;
            }

            var stdMat = materialNode.MaxMaterial.GetParamBlock(0).Owner as IStdMat2;

            if (stdMat != null)
            {
                var babylonMaterial = new BabylonStandardMaterial
                {
                    name          = name,
                    id            = id,
                    ambient       = materialNode.MaxMaterial.GetAmbient(0, false).ToArray(),
                    diffuse       = materialNode.MaxMaterial.GetDiffuse(0, false).ToArray(),
                    specular      = materialNode.MaxMaterial.GetSpecular(0, false).Scale(materialNode.MaxMaterial.GetShinStr(0, false)),
                    specularPower = materialNode.MaxMaterial.GetShininess(0, false) * 256,
                    emissive      =
                        materialNode.MaxMaterial.GetSelfIllumColorOn(0, false)
                            ? materialNode.MaxMaterial.GetSelfIllumColor(0, false).ToArray()
                            : materialNode.MaxMaterial.GetDiffuse(0, false).Scale(materialNode.MaxMaterial.GetSelfIllum(0, false)),
                    alpha = 1.0f - materialNode.MaxMaterial.GetXParency(0, false)
                };

                babylonMaterial.backFaceCulling = !stdMat.TwoSided;
                babylonMaterial.wireframe       = stdMat.Wire;

                // Textures
                BabylonFresnelParameters fresnelParameters;

                babylonMaterial.ambientTexture = ExportTexture(stdMat, 0, out fresnelParameters, babylonScene);                // Ambient
                babylonMaterial.diffuseTexture = ExportTexture(stdMat, 1, out fresnelParameters, babylonScene);                // Diffuse
                if (fresnelParameters != null)
                {
                    babylonMaterial.diffuseFresnelParameters = fresnelParameters;
                }

                babylonMaterial.specularTexture = ExportTexture(stdMat, 2, out fresnelParameters, babylonScene);               // Specular
                babylonMaterial.emissiveTexture = ExportTexture(stdMat, 5, out fresnelParameters, babylonScene);               // Emissive
                if (fresnelParameters != null)
                {
                    babylonMaterial.emissiveFresnelParameters = fresnelParameters;
                    if (babylonMaterial.emissive[0] == 0 &&
                        babylonMaterial.emissive[1] == 0 &&
                        babylonMaterial.emissive[2] == 0 &&
                        babylonMaterial.emissiveTexture == null)
                    {
                        babylonMaterial.emissive = new float[] { 1, 1, 1 };
                    }
                }

                babylonMaterial.opacityTexture = ExportTexture(stdMat, 6, out fresnelParameters, babylonScene, false, true);   // Opacity
                if (fresnelParameters != null)
                {
                    babylonMaterial.opacityFresnelParameters = fresnelParameters;
                    if (babylonMaterial.alpha == 1 &&
                        babylonMaterial.opacityTexture == null)
                    {
                        babylonMaterial.alpha = 0;
                    }
                }

                babylonMaterial.bumpTexture       = ExportTexture(stdMat, 8, out fresnelParameters, babylonScene);             // Bump
                babylonMaterial.reflectionTexture = ExportTexture(stdMat, 9, out fresnelParameters, babylonScene, true);       // Reflection
                if (fresnelParameters != null)
                {
                    if (babylonMaterial.reflectionTexture == null)
                    {
                        RaiseWarning("Fallout cannot be used with reflection channel without a texture", 2);
                    }
                    else
                    {
                        babylonMaterial.reflectionFresnelParameters = fresnelParameters;
                    }
                }

                // Constraints
                if (babylonMaterial.diffuseTexture != null)
                {
                    babylonMaterial.diffuse = new[] { 1.0f, 1.0f, 1.0f };
                }

                if (babylonMaterial.emissiveTexture != null)
                {
                    babylonMaterial.emissive = new float[] { 0, 0, 0 };
                }

                if (babylonMaterial.opacityTexture != null && babylonMaterial.diffuseTexture != null &&
                    babylonMaterial.diffuseTexture.name == babylonMaterial.opacityTexture.name &&
                    babylonMaterial.diffuseTexture.hasAlpha && !babylonMaterial.opacityTexture.getAlphaFromRGB)
                {
                    // This is a alpha testing purpose
                    babylonMaterial.opacityTexture          = null;
                    babylonMaterial.diffuseTexture.hasAlpha = true;
                    RaiseWarning("Opacity texture was removed because alpha from diffuse texture can be use instead", 2);
                    RaiseWarning("If you do not want this behavior, just set Alpha Source = None on your diffuse texture", 2);
                }

                babylonScene.MaterialsList.Add(babylonMaterial);
            }
            else if (materialNode.MaterialClass == "Physical Material")
            {
                var propertyContainer = materialNode.IPropertyContainer;

                var babylonMaterial = new BabylonPBRMetallicRoughnessMaterial
                {
                    name = name,
                    id   = id
                };

                // --- Global ---

                // Alpha
                // ---
                // TODO - Unclear if alpha must be stored within 'alpha' property of BABYLON.Material
                // or within alpha channel of 'baseColor' of BABYLON.PBRMetallicRoughnessMaterial
                // ---
                // TODO - XParency seems computed from several parameters
                // 'Transparency' property is one of them
                // Which value to use?
                var alphaFromXParency          = 1.0f - materialNode.MaxMaterial.GetXParency(0, false);
                var alphaFromPropertyContainer = 1.0f - propertyContainer.GetFloatProperty(17);
                RaiseMessage("alphaFromXParency=" + alphaFromXParency, 2);
                RaiseMessage("alphaFromPropertyContainer=" + alphaFromPropertyContainer, 2);
                babylonMaterial.alpha = alphaFromXParency;

                babylonMaterial.baseColor = materialNode.MaxMaterial.GetDiffuse(0, false).ToArray();

                babylonMaterial.metallic = propertyContainer.GetFloatProperty(6);

                babylonMaterial.roughness = propertyContainer.GetFloatProperty(4);
                if (propertyContainer.GetIntProperty(5) == 1)
                {
                    // Inverse roughness
                    babylonMaterial.roughness = 1 - babylonMaterial.roughness;
                }

                // Self illumination is computed from emission color, luminance, temperature and weight
                babylonMaterial.emissiveColor = materialNode.MaxMaterial.GetSelfIllumColorOn(0, false)
                                                ? materialNode.MaxMaterial.GetSelfIllumColor(0, false).ToArray()
                                                : materialNode.MaxMaterial.GetDiffuse(0, false).Scale(materialNode.MaxMaterial.GetSelfIllum(0, false));

                // --- Textures ---

                babylonMaterial.baseTexture = ExportBaseColorAlphaTexture(materialNode, babylonScene, name);

                if (babylonMaterial.alpha != 1.0f || (babylonMaterial.baseTexture != null && babylonMaterial.baseTexture.hasAlpha))
                {
                    babylonMaterial.transparencyMode = (int)BabylonPBRMetallicRoughnessMaterial.TransparencyMode.ALPHABLEND;
                }

                babylonMaterial.metallicRoughnessTexture = ExportMetallicRoughnessTexture(materialNode, babylonMaterial.metallic, babylonMaterial.roughness, babylonScene, name);

                babylonMaterial.environmentTexture = ExportPBRTexture(materialNode, 3, babylonScene);

                var normalMapAmount = propertyContainer.GetFloatProperty(91);
                babylonMaterial.normalTexture = ExportPBRTexture(materialNode, 30, babylonScene, normalMapAmount);

                babylonMaterial.emissiveTexture = ExportPBRTexture(materialNode, 17, babylonScene);

                // Constraints
                if (babylonMaterial.baseTexture != null)
                {
                    babylonMaterial.baseColor = new[] { 1.0f, 1.0f, 1.0f };
                }

                if (babylonMaterial.emissiveTexture != null)
                {
                    babylonMaterial.emissiveColor = new float[] { 0, 0, 0 };
                }

                babylonScene.MaterialsList.Add(babylonMaterial);
            }
            else
            {
                RaiseWarning("Unsupported material type: " + materialNode.MaterialClass, 2);
            }
        }
Beispiel #10
0
        private void ExportMaterial(Material materialNode, BabylonScene babylonScene)
        {
            var name = materialNode._Mtl.Name;
            var id   = materialNode.GetGuid().ToString();

            RaiseMessage(name, true);

            if (materialNode.NumSubMaterials > 0)
            {
                var babylonMultimaterial = new BabylonMultiMaterial();
                babylonMultimaterial.name = name;
                babylonMultimaterial.id   = id;

                var guids = new List <string>();

                for (var index = 0; index < materialNode.NumSubMaterials; index++)
                {
                    var subMat = materialNode.GetSubMaterial(index) as Material;

                    if (subMat != null)
                    {
                        guids.Add(subMat.GetGuid().ToString());

                        if (!referencedMaterials.Contains(subMat))
                        {
                            referencedMaterials.Add(subMat);
                            ExportMaterial(subMat, babylonScene);
                        }
                    }
                    else
                    {
                        guids.Add(Guid.Empty.ToString());
                    }
                }

                babylonMultimaterial.materials = guids.ToArray();

                babylonScene.MultiMaterialsList.Add(babylonMultimaterial);
            }


            var babylonMaterial = new BabylonMaterial();

            babylonMaterial.name = name;
            babylonMaterial.id   = id;

            babylonMaterial.ambient       = materialNode.GetAmbient(0).ToArray();
            babylonMaterial.diffuse       = materialNode.GetDiffuse(0).ToArray();
            babylonMaterial.specular      = materialNode.GetSpecular(0).Scale(materialNode.GetShininess(0));
            babylonMaterial.specularPower = materialNode.GetShinyStrength(0);

            babylonMaterial.emissive = materialNode.SelfIlluminationColorOn ? materialNode.GetSelfIllumColor(0).ToArray() : materialNode.GetDiffuse(0).Scale(materialNode.GetSelfIllumination(0));
            babylonMaterial.alpha    = 1.0f - materialNode.GetTransparency(0);

            var stdMat = materialNode._Mtl.GetParamBlock(0).Owner as IStdMat2;

            if (stdMat != null)
            {
                // Textures
                babylonMaterial.ambientTexture    = ExportTexture(stdMat, 0, babylonScene); // Ambient
                babylonMaterial.diffuseTexture    = ExportTexture(stdMat, 1, babylonScene); // Diffuse
                babylonMaterial.specularTexture   = ExportTexture(stdMat, 2, babylonScene); // Specular
                babylonMaterial.emissiveTexture   = ExportTexture(stdMat, 5, babylonScene); // Emissive
                babylonMaterial.opacityTexture    = ExportTexture(stdMat, 6, babylonScene); // Opacity
                babylonMaterial.bumpTexture       = ExportTexture(stdMat, 8, babylonScene); // Bump
                babylonMaterial.reflectionTexture = ExportTexture(stdMat, 9, babylonScene); // Reflection

                // Constraints
                if (babylonMaterial.diffuseTexture != null)
                {
                    babylonMaterial.emissive = new [] { 1.0f, 1.0f, 1.0f };
                }

                if (babylonMaterial.emissiveTexture != null)
                {
                    babylonMaterial.emissive = new float[] { 0, 0, 0 };
                }

                if (babylonMaterial.opacityTexture != null && babylonMaterial.diffuseTexture != null &&
                    babylonMaterial.diffuseTexture.name == babylonMaterial.opacityTexture.name &&
                    babylonMaterial.diffuseTexture.hasAlpha && !babylonMaterial.opacityTexture.getAlphaFromRGB)
                {
                    // This is a alpha testing purpose
                    babylonMaterial.opacityTexture          = null;
                    babylonMaterial.diffuseTexture.hasAlpha = true;
                    RaiseWarning("Opacity texture was removed because alpha from diffuse texture can be use instead", true);
                    RaiseWarning("If you do not want this behavior, just set Alpha Source = None on your diffuse texture", true);
                }
            }

            babylonScene.MaterialsList.Add(babylonMaterial);
        }