Пример #1
0
        public static void ConvertAiSceneFromModels(List <Model> models, string outputFileName, TextureDatabase textureDatabase = null)
        {
            SceneUtilities.Export(ConvertAiSceneFromModels(models, textureDatabase), outputFileName);

            var texturesOutputDirectory = Path.GetDirectoryName(outputFileName);

            foreach (var model in models.Where(x => x.TextureSet != null))
            {
                TextureUtilities.SaveTextures(model.TextureSet, texturesOutputDirectory);
            }
        }
Пример #2
0
        private Bitmap _loadTexture(ITexmap texMap)
        {
            IBitmapTex texture = _getBitmapTex(texMap);

            if (texture == null)
            {
                return(null);
            }

            return(TextureUtilities.LoadTexture(texture.Map.FullFilePath, this));
        }
Пример #3
0
        public static void ConvertAiSceneFromObjectSets(List <ObjectSet> objectSets, string outputFileName,
                                                        TextureDatabase textureDatabase = null)
        {
            SceneUtilities.Export(ConvertAiSceneFromObjectSets(objectSets, textureDatabase), outputFileName);

            var texturesOutputDirectory = Path.GetDirectoryName(outputFileName);

            foreach (var objectSet in objectSets.Where(x => x.TextureSet != null))
            {
                TextureUtilities.SaveTextures(objectSet.TextureSet, texturesOutputDirectory);
            }
        }
Пример #4
0
        public static void ConvertAiSceneFromObjectSet(ObjectSet objectSet, string outputFileName,
                                                       TextureDatabase textureDatabase = null, bool appendTags = false)
        {
            SceneUtilities.Export(ConvertAiSceneFromObjectSet(objectSet, textureDatabase, appendTags),
                                  outputFileName);

            if (objectSet.TextureSet != null)
            {
                string texturesOutputDirectory = Path.GetDirectoryName(outputFileName);
                TextureUtilities.SaveTextures(objectSet.TextureSet, texturesOutputDirectory);
            }
        }
Пример #5
0
        public override void DrawTimelineGui(Rect rect)
        {
#if UNITY_EDITOR
            if (EventName != null && name != EventName)
            {
                name = EventName;
                UnityEditor.EditorUtility.SetDirty(this);
            }
#endif
            var guiStyle = new GUIStyle(GUI.skin.box);
            guiStyle.normal.background = TextureUtilities.MakeTexture((int)rect.width, (int)rect.height, new Color(0.54f, 1f, 0.58f),
                                                                      new RectOffset(5, 5, 5, 5), new Color(0f, 0.35f, 0.1f));
            GUI.Box(rect, string.Format("{0:F3}:{1}", StartTime, EventName), guiStyle);
        }
Пример #6
0
        private void UpdateState(List <Texture2D> source, List <Texture2D> copyHolder)
        {
            if (source.Count == 0)
            {
                return;
            }

            copyHolder.Insert(0, TextureUtilities.CopyTexture(Painter.CanvasTexture));
            TextureUtilities.CopyTexture(source.First(), Painter.CanvasTexture);

            source.DestroyAndRemove(0);

            CheckForMaxDepthExceed();
        }
Пример #7
0
        public void RegisterState()
        {
            if (Painter == null)
            {
                return;
            }

            _undoTextures.Insert(0, TextureUtilities.CopyTexture(Painter.CanvasTexture));

            _redoTextures.DestroyAll();
            _redoTextures.Clear();

            CheckForMaxDepthExceed();
        }
Пример #8
0
        public static Ai.Scene ConvertAiSceneFromObjectSets(List <ObjectSet> objectSets,
                                                            TextureDatabase textureDatabase = null)
        {
            var aiScene = new Ai.Scene();

            aiScene.RootNode = new Ai.Node("RootNode");

            foreach (var objectSet in objectSets.Where(x => x.TextureSet != null))
            {
                TextureUtilities.RenameTextures(objectSet.TextureSet, textureDatabase);
            }

            foreach (var objectSet in objectSets)
            {
                foreach (var obj in objectSet.Objects)
                {
                    ConvertAiMaterialsFromMaterials(aiScene, obj.Materials, objectSet.TextureSet);
                }
            }

            var bones         = new List <BoneInfo>();
            var boneParentMap = new Dictionary <string, string>();

            foreach (var objectSet in objectSets)
            {
                foreach (var obj in objectSet.Objects.Where(x => x.Skin != null))
                {
                    foreach (var boneInfo in obj.Skin.Bones)
                    {
                        if (!boneParentMap.ContainsKey(boneInfo.Name))
                        {
                            var parentBone =
                                obj.Skin.Bones.FirstOrDefault(x => x.Id == boneInfo.ParentId);

                            bones.Add(boneInfo);
                            boneParentMap.Add(boneInfo.Name, parentBone?.Name);
                        }
                    }
                }
            }

            ConvertAiNodesFromBones(aiScene, bones, boneParentMap);

            foreach (var objectSet in objectSets)
            {
                ConvertAiNodesFromObjects(aiScene, objectSet.Objects);
            }

            return(aiScene);
        }
Пример #9
0
        public static Ai.Scene ConvertAiSceneFromModels(List <Model> models, TextureDatabase textureDatabase = null)
        {
            var aiScene = new Ai.Scene();

            aiScene.RootNode = new Ai.Node("RootNode");

            foreach (var model in models.Where(x => x.TextureSet != null))
            {
                TextureUtilities.RenameTextures(model.TextureSet, textureDatabase);
            }

            foreach (var model in models)
            {
                foreach (var mesh in model.Meshes)
                {
                    ConvertAiMaterialsFromMaterials(aiScene, mesh.Materials, model.TextureSet);
                }
            }

            var bones         = new List <Bone>();
            var boneParentMap = new Dictionary <string, string>();

            foreach (var model in models)
            {
                foreach (var mesh in model.Meshes.Where(x => x.Skin != null))
                {
                    foreach (var bone in mesh.Skin.Bones)
                    {
                        if (!boneParentMap.ContainsKey(bone.Name))
                        {
                            var parentBone =
                                mesh.Skin.Bones.FirstOrDefault(x => x.Id == bone.ParentId);

                            bones.Add(bone);
                            boneParentMap.Add(bone.Name, parentBone?.Name);
                        }
                    }
                }
            }

            ConvertAiNodesFromBones(aiScene, bones, boneParentMap);

            foreach (var model in models)
            {
                ConvertAiNodesFromMeshes(aiScene, model.Meshes);
            }

            return(aiScene);
        }
Пример #10
0
        private static Ai.TextureSlot ConvertTextureSlotFromTextureId(int textureId, Ai.TextureType type, TextureSet textureList)
        {
            if (textureId == -1 || textureList == null)
            {
                return(default(Ai.TextureSlot));
            }

            var texture = textureList.Textures.FirstOrDefault(x => x.Id == textureId);

            if (texture != null)
            {
                return(new Ai.TextureSlot(TextureUtilities.GetFileName(texture), type, 0, Ai.TextureMapping.FromUV, 0, 0, Ai.TextureOperation.Add, Ai.TextureWrapMode.Wrap, Ai.TextureWrapMode.Wrap, 0));
            }

            return(default(Ai.TextureSlot));
        }
Пример #11
0
    void Start()
    {
        //Check if already saved a texture in disk with key "myTexture"
        if (TextureUtilities.IsTextureSaved("myTexture"))
        {
            //Load saved texture
            imageTextureCopy = TextureUtilities.Load("myTexture");

            //Assign loaded texture to your sprite
            imageSprite.sprite = TextureUtilities.GetSpriteFromTexture(imageTextureCopy);
        }

        //Get texture copy in order to manipulate its data and pixels.
        //you can't access texture data directly, it will throw an error : (Texture is not readable)
        imageTextureCopy = TextureUtilities.GetTextureCopy(imageSprite.sprite.texture);
    }
Пример #12
0
        public static CNMutableContact ToCNMutableContact(this Contact contact)
        {
            if (contact == null)
            {
                return(null);
            }

            CNMutableContact nativeContact = new CNMutableContact();

            if (contact.FirstName != null)
            {
                nativeContact.GivenName = NSString.StringWithUTF8String(contact.FirstName);
            }

            if (contact.MiddleName != null)
            {
                nativeContact.MiddleName = NSString.StringWithUTF8String(contact.MiddleName);
            }

            if (contact.LastName != null)
            {
                nativeContact.FamilyName = NSString.StringWithUTF8String(contact.LastName);
            }

            if (contact.Company != null)
            {
                nativeContact.OrganizationName = NSString.StringWithUTF8String(contact.Company);
            }


            if (contact.Birthday != null)
            {
                nativeContact.Birthday = contact.Birthday.Value.ToNSDateComponents();
            }

            nativeContact.EmailAddresses = ToCNCotactEmails(contact.Emails);
            nativeContact.PhoneNumbers   = ToCNContactPhoneNumbers(contact.PhoneNumbers);

            if (contact.Photo != null)
            {
                byte[] rawData = TextureUtilities.EncodeAsByteArray(contact.Photo, ImageFormat.PNG);
                nativeContact.ImageData = NSData.DataWithBytes(rawData, (uint)rawData.Length);
            }

            return(nativeContact);
        }
Пример #13
0
        private GLTFBufferView WriteImageToGltfBuffer(GLTF gltf, GLTFImage gltfImage, string imageSourcePath = null, Bitmap imageBitmap = null, long textureQuality = 100)
        {
            byte[] imageBytes = null;
            if (imageBitmap != null)
            {
                // try our best to get extension - default will be png which is the looseless format.
                var extension    = gltfImage.FileExtension ?? (gltfImage.uri != null ? Path.GetExtension(gltfImage.uri) : null);
                var outputFormat = extension != null?TextureUtilities.GetImageFormat(gltfImage.FileExtension) : ImageFormat.Png;

                using (MemoryStream m = new MemoryStream())
                {
                    // this use the SAME method for GLTF
                    TextureUtilities.SaveBitmap(m, imageBitmap, outputFormat, textureQuality);
                    imageBytes = m.ToArray();
                }
            }
            else
            {
                imageBytes = File.ReadAllBytes(imageSourcePath);
            }

            // Chunk must be padded with trailing zeros (0x00) to satisfy alignment requirements
            imageBytes = padChunk(imageBytes, 4, 0x00);

            // BufferView - Image
            var buffer          = gltf.buffer;
            var imageBufferView = new GLTFBufferView
            {
                name       = "bufferViewImage",
                buffer     = buffer.index,
                Buffer     = buffer,
                byteOffset = buffer.byteLength
            };

            imageBufferView.index = gltf.BufferViewsList.Count;
            gltf.BufferViewsList.Add(imageBufferView);

            imageBufferView.bytesList.AddRange(imageBytes);
            imageBufferView.byteLength        += imageBytes.Length;
            imageBufferView.Buffer.byteLength += imageBytes.Length;
            imageBufferView.Buffer.bytesList.AddRange(imageBufferView.bytesList);

            return(imageBufferView);
        }
Пример #14
0
        public void SaveImage(Texture2D image, string name, ImageFormat format = ImageFormat.JPG, Action <string> callback = null)
        {
            if (callback == null)
            {
                Debug.LogError(NullCallbackMessage);
                return;
            }

            if (image == null)
            {
                callback(NullImageMessage);
                return;
            }

            if (nativeGallery == null)
            {
                callback(NullNativeGalleryMessage);
                return;
            }

            nativeGallery.Call(NativeSaveImageName, TextureUtilities.Encode(image, format), name, (int)format, new AndroidSaveImageProxy(callback), false); // false = saveToInternal
        }
        private GLTFTextureInfo ExportEmissiveTexture(BabylonStandardMaterial babylonMaterial, GLTF gltf, float[] defaultEmissive, float[] defaultDiffuse)
        {
            // Use one as a reference for UVs parameters
            var babylonTexture = babylonMaterial.emissiveTexture != null ? babylonMaterial.emissiveTexture : babylonMaterial.diffuseTexture;

            if (babylonTexture == null)
            {
                return(null);
            }

            // Anticipate if a black texture is going to be export
            if (babylonMaterial.emissiveTexture == null && defaultEmissive.IsAlmostEqualTo(new float[] { 0, 0, 0 }, 0))
            {
                return(null);
            }

            // Check if the texture has already been exported
            if (GetRegisteredEmissive(babylonMaterial, defaultDiffuse, defaultEmissive) != null)
            {
                return(GetRegisteredEmissive(babylonMaterial, defaultDiffuse, defaultEmissive));
            }

            Bitmap emissivePremultipliedBitmap = null;

            if (exportParameters.writeTextures)
            {
                // Emissive
                Bitmap emissiveBitmap = null;
                if (babylonMaterial.emissiveTexture != null)
                {
                    emissiveBitmap = TextureUtilities.LoadTexture(babylonMaterial.emissiveTexture.originalPath, logger);
                }

                // Diffuse
                Bitmap diffuseBitmap = null;
                if (babylonMaterial.diffuseTexture != null)
                {
                    diffuseBitmap = TextureUtilities.LoadTexture(babylonMaterial.diffuseTexture.originalPath, logger);
                }

                if (emissiveBitmap != null || diffuseBitmap != null)
                {
                    // Retreive dimensions
                    int width              = 0;
                    int height             = 0;
                    var haveSameDimensions = TextureUtilities.GetMinimalBitmapDimensions(out width, out height, emissiveBitmap, diffuseBitmap);
                    if (!haveSameDimensions)
                    {
                        logger.RaiseError("Emissive and diffuse maps should have same dimensions", 2);
                    }

                    // Create pre-multiplied emissive map
                    emissivePremultipliedBitmap = new Bitmap(width, height);
                    for (int x = 0; x < width; x++)
                    {
                        for (int y = 0; y < height; y++)
                        {
                            var _emissive = emissiveBitmap != null?emissiveBitmap.GetPixel(x, y).toArrayRGB().Multiply(1f / 255.0f) : defaultEmissive;

                            var _diffuse = diffuseBitmap != null?diffuseBitmap.GetPixel(x, y).toArrayRGB().Multiply(1f / 255.0f) : defaultDiffuse;

                            var emissivePremultiplied = _emissive.Multiply(_diffuse);

                            Color colorEmissivePremultiplied = Color.FromArgb(
                                (int)(emissivePremultiplied[0] * 255),
                                (int)(emissivePremultiplied[1] * 255),
                                (int)(emissivePremultiplied[2] * 255)
                                );
                            emissivePremultipliedBitmap.SetPixel(x, y, colorEmissivePremultiplied);
                        }
                    }
                }
            }

            var emissiveTextureInfo = ExportBitmapTexture(gltf, babylonTexture, emissivePremultipliedBitmap);

            // Register the texture for optimisation
            RegisterEmissive(emissiveTextureInfo, babylonMaterial, defaultDiffuse, defaultEmissive);

            return(emissiveTextureInfo);
        }
        private BabylonTexture ExportTexture(ITexmap texMap, BabylonScene babylonScene, float amount = 1.0f, bool allowCube = false, bool forceAlpha = false)
        {
            IBitmapTex texture = _getBitmapTex(texMap, false);

            if (texture == null)
            {
                float specialAmount;
                var   specialTexMap = _getSpecialTexmap(texMap, out specialAmount);
                texture = _getBitmapTex(specialTexMap, false);
                amount *= specialAmount;
            }

            if (texture == null)
            {
                return(null);
            }

            var sourcePath = texture.Map.FullFilePath;

            if (sourcePath == null || sourcePath == "")
            {
                RaiseWarning("Texture path is missing.", 2);
                return(null);
            }

            RaiseMessage("Export texture named: " + Path.GetFileName(sourcePath), 2);

            var validImageFormat = TextureUtilities.GetValidImageFormat(Path.GetExtension(sourcePath));

            if (validImageFormat == null)
            {
                // Image format is not supported by the exporter
                RaiseWarning(string.Format("Format of texture {0} is not supported by the exporter. Consider using a standard image format like jpg or png.", Path.GetFileName(sourcePath)), 3);
                return(null);
            }
            var textureID = texture.GetGuid().ToString();

            if (textureMap.ContainsKey(textureID))
            {
                return(textureMap[textureID]);
            }
            else
            {
                var babylonTexture = new BabylonTexture(textureID)
                {
                    name = Path.GetFileNameWithoutExtension(texture.MapName) + "." + validImageFormat
                };
                RaiseMessage($"texture id = {babylonTexture.Id}", 2);

                // Level
                babylonTexture.level = amount;

                // Alpha
                if (forceAlpha)
                {
                    babylonTexture.hasAlpha        = true;
                    babylonTexture.getAlphaFromRGB = (texture.AlphaSource == 2) || (texture.AlphaSource == 3); // 'RGB intensity' or 'None (Opaque)'
                }
                else
                {
                    babylonTexture.hasAlpha        = (texture.AlphaSource != 3); // Not 'None (Opaque)'
                    babylonTexture.getAlphaFromRGB = (texture.AlphaSource == 2); // 'RGB intensity'
                }

                // UVs
                var uvGen = _exportUV(texture.UVGen, babylonTexture);

                // Animations
                var animations = new List <BabylonAnimation>();
                ExportFloatAnimation("uOffset", animations, key => new[] { uvGen.GetUOffs(key) });
                ExportFloatAnimation("vOffset", animations, key => new[] { -uvGen.GetVOffs(key) });
                ExportFloatAnimation("uScale", animations, key => new[] { uvGen.GetUScl(key) });
                ExportFloatAnimation("vScale", animations, key => new[] { uvGen.GetVScl(key) });
                ExportFloatAnimation("uAng", animations, key => new[] { uvGen.GetUAng(key) });
                ExportFloatAnimation("vAng", animations, key => new[] { uvGen.GetVAng(key) });
                ExportFloatAnimation("wAng", animations, key => new[] { uvGen.GetWAng(key) });
                babylonTexture.animations = animations.ToArray();

                // Copy texture to output
                if (isBabylonExported)
                {
                    var destPath = Path.Combine(babylonScene.OutputPath, babylonTexture.name);
                    TextureUtilities.CopyTexture(sourcePath, destPath, exportParameters.txtQuality, this);

                    // Is cube
                    _exportIsCube(Path.Combine(babylonScene.OutputPath, babylonTexture.name), babylonTexture, allowCube);
                }
                else
                {
                    babylonTexture.isCube = false;
                }
                babylonTexture.originalPath = sourcePath;

                return(babylonTexture);
            }
        }
        private BabylonTexture ExportSpecularTexture(IIGameMaterial materialNode, float[] specularColor, BabylonScene babylonScene)
        {
            ITexmap specularColorTexMap = _getTexMap(materialNode, 2);
            ITexmap specularLevelTexMap = _getTexMap(materialNode, 3);

            // --- Babylon texture ---

            var specularColorTexture = _getBitmapTex(specularColorTexMap);
            var specularLevelTexture = _getBitmapTex(specularLevelTexMap);

            if (specularLevelTexture == null)
            {
                // Copy specular color image
                // Assume specular color texture is already pre-multiplied by a global specular level value
                // So do not use global specular level
                return(ExportTexture(specularColorTexture, babylonScene));
            }

            // Use one as a reference for UVs parameters
            var texture = specularColorTexture != null ? specularColorTexture : specularLevelTexture;

            if (texture == null)
            {
                return(null);
            }

            RaiseMessage("Multiply specular color and level textures", 2);

            string nameText = null;

            nameText = (specularColorTexture != null ? Path.GetFileNameWithoutExtension(specularColorTexture.Map.FullFilePath) : TextureUtilities.ColorToStringName(specularColor)) +
                       Path.GetFileNameWithoutExtension(specularLevelTexture.Map.FullFilePath) + "_specularColor";

            var textureID = texture.GetGuid().ToString();

            if (textureMap.ContainsKey(textureID))
            {
                return(textureMap[textureID]);
            }
            else
            {
                var babylonTexture = new BabylonTexture(textureID)
                {
                    name = nameText + ".jpg" // TODO - unsafe name, may conflict with another texture name
                };

                // Level
                babylonTexture.level = 1.0f;

                // UVs
                var uvGen = _exportUV(texture.UVGen, babylonTexture);

                // Is cube
                _exportIsCube(texture.Map.FullFilePath, babylonTexture, false);


                // --- Multiply specular color and level maps ---

                // Alpha
                babylonTexture.hasAlpha        = false;
                babylonTexture.getAlphaFromRGB = false;

                if (exportParameters.writeTextures)
                {
                    // Load bitmaps
                    var specularColorBitmap = _loadTexture(specularColorTexMap);
                    var specularLevelBitmap = _loadTexture(specularLevelTexMap);

                    if (specularLevelBitmap == null)
                    {
                        // Copy specular color image
                        RaiseError("Failed to load specular level texture. Specular color is exported alone.", 3);
                        return(ExportTexture(specularColorTexture, babylonScene));
                    }

                    // Retreive dimensions
                    int width              = 0;
                    int height             = 0;
                    var haveSameDimensions = TextureUtilities.GetMinimalBitmapDimensions(out width, out height, specularColorBitmap, specularLevelBitmap);
                    if (!haveSameDimensions)
                    {
                        RaiseError("Specular color and specular level maps should have same dimensions", 3);
                    }

                    // Create pre-multiplied specular color map
                    var _specularColor = Color.FromArgb(
                        (int)(specularColor[0] * 255),
                        (int)(specularColor[1] * 255),
                        (int)(specularColor[2] * 255));
                    Bitmap specularColorPreMultipliedBitmap = new Bitmap(width, height);
                    for (int x = 0; x < width; x++)
                    {
                        for (int y = 0; y < height; y++)
                        {
                            var specularColorAtPixel = specularColorBitmap != null?specularColorBitmap.GetPixel(x, y) : _specularColor;

                            var specularLevelAtPixel = specularLevelBitmap.GetPixel(x, y);

                            var specularColorPreMultipliedAtPixel = specularColorAtPixel.multiply(specularLevelAtPixel);

                            specularColorPreMultipliedBitmap.SetPixel(x, y, specularColorPreMultipliedAtPixel);
                        }
                    }

                    // Write bitmap
                    if (isBabylonExported)
                    {
                        RaiseMessage($"Texture | write image '{babylonTexture.name}'", 3);
                        TextureUtilities.SaveBitmap(specularColorPreMultipliedBitmap, babylonScene.OutputPath, babylonTexture.name, ImageFormat.Jpeg, exportParameters.txtQuality, this);
                    }
                    else
                    {
                        // Store created bitmap for further use in gltf export
                        babylonTexture.bitmap = specularColorPreMultipliedBitmap;
                    }
                }
                textureMap.Add(babylonTexture.Id, babylonTexture);
                return(babylonTexture);
            }
        }
        private BabylonTexture ExportORMTexture(ITexmap ambientOcclusionTexMap, ITexmap roughnessTexMap, ITexmap metallicTexMap, float metallic, float roughness, BabylonScene babylonScene, bool invertRoughness)
        {
            // --- Babylon texture ---

            var metallicTexture         = _getBitmapTex(metallicTexMap);
            var roughnessTexture        = _getBitmapTex(roughnessTexMap);
            var ambientOcclusionTexture = _getBitmapTex(ambientOcclusionTexMap);

            // Use metallic or roughness texture as a reference for UVs parameters
            var texture = metallicTexture != null ? metallicTexture : roughnessTexture;

            if (texture == null)
            {
                return(null);
            }

            RaiseMessage("Export ORM texture", 2);

            var textureID = texture.GetGuid().ToString();

            if (textureMap.ContainsKey(textureID))
            {
                return(textureMap[textureID]);
            }
            else
            {
                var babylonTexture = new BabylonTexture(textureID)
                {
                    name = (ambientOcclusionTexMap != null ? Path.GetFileNameWithoutExtension(ambientOcclusionTexture.Map.FileName) : "") +
                           (roughnessTexMap != null ? Path.GetFileNameWithoutExtension(roughnessTexture.Map.FileName) : ("" + (int)(roughness * 255))) +
                           (metallicTexMap != null ? Path.GetFileNameWithoutExtension(metallicTexture.Map.FileName) : ("" + (int)(metallic * 255))) + ".jpg" // TODO - unsafe name, may conflict with another texture name
                };

                // UVs
                var uvGen = _exportUV(texture.UVGen, babylonTexture);

                // Is cube
                _exportIsCube(texture.Map.FullFilePath, babylonTexture, false);


                // --- Merge metallic and roughness maps ---

                if (!isTextureOk(metallicTexMap) && !isTextureOk(roughnessTexMap))
                {
                    return(null);
                }

                if (exportParameters.writeTextures)
                {
                    // Load bitmaps
                    var metallicBitmap         = _loadTexture(metallicTexMap);
                    var roughnessBitmap        = _loadTexture(roughnessTexMap);
                    var ambientOcclusionBitmap = _loadTexture(ambientOcclusionTexMap);

                    // Retreive dimensions
                    int width              = 0;
                    int height             = 0;
                    var haveSameDimensions = TextureUtilities.GetMinimalBitmapDimensions(out width, out height, metallicBitmap, roughnessBitmap, ambientOcclusionBitmap);
                    if (!haveSameDimensions)
                    {
                        RaiseError((ambientOcclusionBitmap != null ? "Occlusion, roughness and metallic " : "Metallic and roughness") + " maps should have same dimensions", 3);
                    }

                    // Create ORM map
                    Bitmap ormBitmap = new Bitmap(width, height);
                    for (int x = 0; x < width; x++)
                    {
                        for (int y = 0; y < height; y++)
                        {
                            int _occlusion = ambientOcclusionBitmap != null?ambientOcclusionBitmap.GetPixel(x, y).R : 0;

                            int _roughness = roughnessBitmap != null ? (invertRoughness ? 255 - roughnessBitmap.GetPixel(x, y).G : roughnessBitmap.GetPixel(x, y).G) : (int)(roughness * 255.0f);
                            int _metallic  = metallicBitmap != null?metallicBitmap.GetPixel(x, y).B : (int)(metallic * 255.0f);

                            // The occlusion values are sampled from the R channel.
                            // The roughness values are sampled from the G channel.
                            // The metalness values are sampled from the B channel.
                            Color colorMetallicRoughness = Color.FromArgb(_occlusion, _roughness, _metallic);
                            ormBitmap.SetPixel(x, y, colorMetallicRoughness);
                        }
                    }

                    // Write bitmap
                    if (isBabylonExported)
                    {
                        RaiseMessage($"Texture | write image '{babylonTexture.name}'", 3);
                        TextureUtilities.SaveBitmap(ormBitmap, babylonScene.OutputPath, babylonTexture.name, ImageFormat.Jpeg, exportParameters.txtQuality, this);
                    }
                    else
                    {
                        // Store created bitmap for further use in gltf export
                        babylonTexture.bitmap = ormBitmap;
                    }
                }
                textureMap[babylonTexture.Id] = babylonTexture;
                return(babylonTexture);
            }
        }
        /// <returns></returns>
        private BabylonTexture ExportBaseColorAlphaTexture(ITexmap baseColorTexMap, ITexmap alphaTexMap, float[] baseColor, float alpha, BabylonScene babylonScene, string materialName, bool isOpacity = false)
        {
            // --- Babylon texture ---

            var baseColorTexture = _getBitmapTex(baseColorTexMap);
            var alphaTexture     = _getBitmapTex(alphaTexMap);

            var texture = baseColorTexture != null ? baseColorTexture : alphaTexture;

            if (texture == null)
            {
                return(null);
            }

            var baseColorTextureMapExtension = Path.GetExtension(baseColorTexture.Map.FullFilePath).ToLower();

            if (alphaTexture == null && baseColorTexture != null && alpha == 1)
            {
                if (baseColorTexture.AlphaSource == 0 &&
                    (baseColorTextureMapExtension == ".tif" || baseColorTextureMapExtension == ".tiff"))
                {
                    RaiseWarning($"Diffuse texture named {baseColorTexture.Map.FullFilePath} is a .tif file and its Alpha Source is 'Image Alpha' by default.", 3);
                    RaiseWarning($"If you don't want material to be in BLEND mode, set diffuse texture Alpha Source to 'None (Opaque)'", 3);
                }


                if (baseColorTexture.AlphaSource == 3 && // 'None (Opaque)'
                    baseColorTextureMapExtension == ".jpg" || baseColorTextureMapExtension == ".jpeg" || baseColorTextureMapExtension == ".bmp" || baseColorTextureMapExtension == ".png")
                {
                    // Copy base color image
                    return(ExportTexture(baseColorTexture, babylonScene));
                }
            }

            // Use one as a reference for UVs parameters


            RaiseMessage("Export baseColor+Alpha texture", 2);

            string nameText = null;

            nameText = (baseColorTexture != null ? Path.GetFileNameWithoutExtension(baseColorTexture.Map.FullFilePath) : TextureUtilities.ColorToStringName(baseColor));

            var textureID = texture.GetGuid().ToString();

            if (textureMap.ContainsKey(textureID))
            {
                return(textureMap[textureID]);
            }
            else
            {
                var babylonTexture = new BabylonTexture(textureID)
                {
                    name = nameText // TODO - unsafe name, may conflict with another texture name
                };

                // Level
                babylonTexture.level = 1.0f;

                // UVs
                var uvGen = _exportUV(texture.UVGen, babylonTexture);

                // Is cube
                _exportIsCube(texture.Map.FullFilePath, babylonTexture, false);


                // --- Merge baseColor and alpha maps ---

                var hasBaseColor = isTextureOk(baseColorTexMap);
                var hasAlpha     = isTextureOk(alphaTexMap);

                // Alpha

                // If the texture file format does not traditionally support an alpha channel, export the base texture as opaque
                if (baseColorTextureMapExtension == ".jpg" || baseColorTextureMapExtension == ".jpeg" || baseColorTextureMapExtension == ".bmp")
                {
                    babylonTexture.hasAlpha = false;
                }
                else
                {
                    babylonTexture.hasAlpha = isTextureOk(alphaTexMap) || (isTextureOk(baseColorTexMap) && baseColorTexture.AlphaSource == 0) || alpha < 1.0f;
                }
                babylonTexture.getAlphaFromRGB = false;
                if ((!isTextureOk(alphaTexMap) && alpha == 1.0f && (isTextureOk(baseColorTexMap) && baseColorTexture.AlphaSource == 0)) &&
                    (baseColorTextureMapExtension == ".tif" || baseColorTextureMapExtension == ".tiff"))
                {
                    RaiseWarning($"Diffuse texture named {baseColorTexture.Map.FullFilePath} is a .tif file and its Alpha Source is 'Image Alpha' by default.", 3);
                    RaiseWarning($"If you don't want material to be in BLEND mode, set diffuse texture Alpha Source to 'None (Opaque)'", 3);
                }

                if (!hasBaseColor && !hasAlpha)
                {
                    return(null);
                }

                // Set image format
                ImageFormat imageFormat = babylonTexture.hasAlpha ? ImageFormat.Png : ImageFormat.Jpeg;
                babylonTexture.name += imageFormat == ImageFormat.Png ? ".png" : ".jpg";

                // --- Merge baseColor and alpha maps ---

                if (exportParameters.writeTextures)
                {
                    // Load bitmaps
                    var baseColorBitmap = _loadTexture(baseColorTexMap);
                    var alphaBitmap     = _loadTexture(alphaTexMap);

                    // Retreive dimensions
                    int width              = 0;
                    int height             = 0;
                    var haveSameDimensions = TextureUtilities.GetMinimalBitmapDimensions(out width, out height, baseColorBitmap, alphaBitmap);
                    if (!haveSameDimensions)
                    {
                        RaiseError("Base color and transparency color maps should have same dimensions", 3);
                    }

                    var getAlphaFromRGB = alphaTexture != null && ((alphaTexture.AlphaSource == 2) || (alphaTexture.AlphaSource == 3)); // 'RGB intensity' or 'None (Opaque)'

                    // Create baseColor+alpha map
                    var _baseColor = Color.FromArgb(
                        (int)(baseColor[0] * 255),
                        (int)(baseColor[1] * 255),
                        (int)(baseColor[2] * 255));
                    var    _alpha = (int)(alpha * 255);
                    Bitmap baseColorAlphaBitmap = new Bitmap(width, height);
                    for (int x = 0; x < width; x++)
                    {
                        for (int y = 0; y < height; y++)
                        {
                            var baseColorAtPixel = baseColorBitmap != null?baseColorBitmap.GetPixel(x, y) : _baseColor;

                            Color baseColorAlpha;
                            if (alphaBitmap != null)
                            {
                                // Retreive alpha from alpha texture
                                Color alphaColor   = alphaBitmap.GetPixel(x, y);
                                int   alphaAtPixel = getAlphaFromRGB ? alphaColor.R : alphaColor.A;
                                if (isOpacity == false)
                                {
                                    // Convert transparency to opacity
                                    alphaAtPixel = 255 - alphaAtPixel;
                                }
                                baseColorAlpha = Color.FromArgb(alphaAtPixel, baseColorAtPixel);
                            }
                            else if (baseColorTexture != null && baseColorTexture.AlphaSource == 0) // Alpha source is 'Image Alpha'
                            {
                                // Use all channels from base color
                                baseColorAlpha = baseColorAtPixel;
                            }
                            else
                            {
                                // Use RGB channels from base color and default alpha
                                baseColorAlpha = Color.FromArgb(_alpha, baseColorAtPixel.R, baseColorAtPixel.G, baseColorAtPixel.B);
                            }
                            baseColorAlphaBitmap.SetPixel(x, y, baseColorAlpha);
                        }
                    }

                    // Write bitmap
                    if (isBabylonExported)
                    {
                        RaiseMessage($"Texture | write image '{babylonTexture.name}'", 3);
                        TextureUtilities.SaveBitmap(baseColorAlphaBitmap, babylonScene.OutputPath, babylonTexture.name, imageFormat, exportParameters.txtQuality, this);
                    }
                    else
                    {
                        // Store created bitmap for further use in gltf export
                        babylonTexture.bitmap = baseColorAlphaBitmap;
                    }
                }

                return(babylonTexture);
            }
        }
        private BabylonTexture ExportClearCoatTexture(ITexmap intensityTexMap, ITexmap roughnessTexMap, float coatWeight, float coatRoughness, BabylonScene babylonScene, string materialName, bool invertRoughness)
        {
            // --- Babylon texture ---
            var intensityTexture = _getBitmapTex(intensityTexMap);
            var roughnessTexture = _getBitmapTex(roughnessTexMap);

            var texture = intensityTexture != null ? intensityTexture : roughnessTexture;

            if (texture == null)
            {
                return(null);
            }

            // Use one as a reference for UVs parameters

            RaiseMessage("Export Clear Coat weight+roughness texture", 2);

            string nameText = Path.GetFileNameWithoutExtension(texture.Map.FullFilePath);

            var textureID = texture.GetGuid().ToString();

            if (textureMap.ContainsKey(textureID))
            {
                return(textureMap[textureID]);
            }
            else
            {
                var babylonTexture = new BabylonTexture(textureID)
                {
                    name = nameText // TODO - unsafe name, may conflict with another texture name
                };

                // Level
                babylonTexture.level = 1.0f;

                // UVs
                var uvGen = _exportUV(texture.UVGen, babylonTexture);

                // Is cube
                _exportIsCube(texture.Map.FullFilePath, babylonTexture, false);

                // --- Merge maps ---
                var hasIntensity = isTextureOk(intensityTexture);
                var hasRoughness = isTextureOk(roughnessTexture);
                if (!hasIntensity && !hasRoughness)
                {
                    return(null);
                }

                // Set image format
                ImageFormat imageFormat = ImageFormat.Jpeg;
                babylonTexture.name += ".jpg";

                if (exportParameters.writeTextures)
                {
                    // Load bitmaps
                    var intensityBitmap = _loadTexture(intensityTexture);
                    var roughnessBitmap = _loadTexture(roughnessTexture);

                    // Retreive dimensions
                    int width              = 0;
                    int height             = 0;
                    var haveSameDimensions = TextureUtilities.GetMinimalBitmapDimensions(out width, out height, intensityBitmap, roughnessBitmap);
                    if (!haveSameDimensions)
                    {
                        RaiseError("Base color and transparency color maps should have same dimensions", 3);
                    }

                    // Create map
                    var    _intensity = (int)(coatWeight * 255);
                    var    _roughness = (int)(coatRoughness * 255);
                    Bitmap intensityRoughnessBitmap = new Bitmap(width, height);
                    for (int x = 0; x < width; x++)
                    {
                        for (int y = 0; y < height; y++)
                        {
                            var intensityAtPixel = (intensityBitmap == null) ? _intensity : intensityBitmap.GetPixel(x, y).R;

                            Color intensityRoughness;
                            if (roughnessBitmap == null)
                            {
                                intensityRoughness = Color.FromArgb(intensityAtPixel, _roughness, 0);
                            }
                            else
                            {
                                var roughnessAtPixel = (roughnessBitmap == null) ?
                                                       _roughness :
                                                       invertRoughness ? 255 - roughnessBitmap.GetPixel(x, y).G : roughnessBitmap.GetPixel(x, y).G;

                                intensityRoughness = Color.FromArgb(intensityAtPixel, roughnessAtPixel, 0);
                            }
                            intensityRoughnessBitmap.SetPixel(x, y, intensityRoughness);
                        }
                    }

                    // Write bitmap
                    if (isBabylonExported)
                    {
                        RaiseMessage($"Texture | write image '{babylonTexture.name}'", 3);
                        TextureUtilities.SaveBitmap(intensityRoughnessBitmap, babylonScene.OutputPath, babylonTexture.name, imageFormat, exportParameters.txtQuality, this);
                    }
                    else
                    {
                        // Store created bitmap for further use in gltf export
                        babylonTexture.bitmap = intensityRoughnessBitmap;
                    }
                }

                return(babylonTexture);
            }
        }
Пример #21
0
        static IEnumerable <tk2DSpriteData> ReadSpritesFromData(SpriteCollectionData data)
        {
            var mainTexture = data.MainTexture as Texture2D;

            using (var progress = new ProgressBar(data.Definitions.GetLength(0) - 1, "Unpacking", "Unpacking TK2DSpriteDefinition", true))
            {
                using (var readContext = new ReadableTextureContext(mainTexture))
                {
                    for (int i = 0; i < data.Definitions.GetLength(0); i++)
                    {
                        progress.GoToNextStep();
                        var sprite = data.Definitions[i];

                        Vector2 uvOffset = new Vector2(0.001f, 0.001f);

                        Vector2 PostProcessedBL = Vector2.zero;
                        Vector2 PostProcessedTR = Vector2.zero;

                        bool rotated = false;

                        if (sprite.UVs[0].x == sprite.UVs[1].x && sprite.UVs[2].x == sprite.UVs[3].x)
                        {
                            rotated = true;
                        }


                        if (rotated)
                        {
                            PostProcessedBL = sprite.UVs[1];
                            PostProcessedTR = sprite.UVs[2];
                        }
                        else
                        {
                            PostProcessedBL = sprite.UVs[0];
                            PostProcessedTR = sprite.UVs[3];
                        }

                        int PreBLx = Mathf.RoundToInt((PostProcessedBL.x * mainTexture.width) - uvOffset.x);
                        int PreTRy = Mathf.RoundToInt(((PostProcessedBL.y) * mainTexture.height) - uvOffset.y);
                        int PreTRx = Mathf.RoundToInt((PostProcessedTR.x * mainTexture.width) + uvOffset.x);
                        int PreBLy = Mathf.RoundToInt(((PostProcessedTR.y) * mainTexture.height) + uvOffset.y);

                        int PreWidth  = Mathf.Abs(PreBLx - PreTRx);
                        int PreHeight = Mathf.Abs(PreBLy - PreTRy);

                        Orientation orientation = Orientation.Up;

                        if (PostProcessedBL.x < PostProcessedTR.x && PostProcessedBL.y < PostProcessedTR.y)
                        {
                            orientation = Orientation.Up;
                        }
                        else if (PostProcessedBL.x < PostProcessedTR.x && PostProcessedBL.y > PostProcessedTR.y)
                        {
                            orientation = Orientation.Right;
                        }
                        else if (PostProcessedBL.x > PostProcessedTR.x && PostProcessedBL.y > PostProcessedTR.y)
                        {
                            orientation = Orientation.Down;
                        }
                        else if (PostProcessedBL.x > PostProcessedTR.x && PostProcessedBL.y < PostProcessedTR.y)
                        {
                            orientation = Orientation.Left;
                        }

                        Vector2Int Min = new Vector2Int(Mathf.RoundToInt(Mathf.Min(PreBLx, PreTRx)), Mathf.RoundToInt(Mathf.Min(PreBLy, PreTRy)));

                        Vector2Int Max = new Vector2Int(Mathf.RoundToInt(Mathf.Max(PreBLx, PreTRx)), Mathf.RoundToInt(Mathf.Max(PreBLy, PreTRy)));

                        Vector2Int SpriteDimensions = new Vector2Int(Mathf.Abs(Max.x - Min.x) + 1, Mathf.Abs(Max.y - Min.y) + 1);

                        Texture2D texture = new Texture2D(SpriteDimensions.x, SpriteDimensions.y);

                        if (Min.x < 0 || Min.y < 0 || Min.x + SpriteDimensions.x - 1 >= mainTexture.width || Min.y + SpriteDimensions.y - 1 >= mainTexture.height)
                        {
                            continue;
                        }

                        var test = mainTexture.GetPixels(Min.x, Min.y, SpriteDimensions.x, SpriteDimensions.y);

                        texture.SetPixels(test);


                        switch (orientation)
                        {
                        case Orientation.Up:
                            texture.Rotate(RotationType.None);
                            break;

                        case Orientation.Right:
                            texture.Rotate(RotationType.Right);
                            break;

                        case Orientation.Down:
                            texture.Rotate(RotationType.HalfFullRotation);
                            break;

                        case Orientation.Left:
                            texture.Rotate(RotationType.Left);
                            break;

                        default:
                            break;
                        }


                        if (sprite.Flipped)
                        {
                            TextureUtilities.FlipHorizontally(texture);
                        }
                        texture.name = sprite.Name;

                        var worldSize = GetWorldSize(sprite.Positions);

                        //TODO
                        yield return(new tk2DSpriteData()
                        {
                            Name = sprite.Name,
                            Pivot = GetPivot(sprite.Positions),
                            Texture = texture,
                            UVDimensions = new Vector2Int(PreWidth, PreHeight),
                            PixelsPerUnit = texture.width / worldSize.x,
                            SpriteCoords = new Rect(Min.x, Min.y, Max.x - Min.x + 1, Max.y - Min.y + 1)
                        });
                    }
                }
            }
        }
Пример #22
0
 private void LoadTexture(Color col)
 {
     _coverage = TextureUtilities.CreateTextureFromColor(32, 32, col);
 }
Пример #23
0
        public void Export(ExportParameters exportParameters)
        {
            this.exportParameters = exportParameters;
            IINode exportNode = null;

            if (exportParameters is MaxExportParameters)
            {
                MaxExportParameters maxExporterParameters = (exportParameters as MaxExportParameters);
                exportNode = maxExporterParameters.exportNode;
                if (maxExporterParameters.flattenScene)
                {
                    FlattenHierarchy(exportNode);
                }
                if (maxExporterParameters.mergeInheritedContainers)
                {
                    ExportClosedContainers();
                }
            }



            this.scaleFactor = Tools.GetScaleFactorToMeters();

            var scaleFactorFloat = 1.0f;
            // Check input text is valid
            float scaleFactor = exportParameters.scaleFactor;

            long quality = exportParameters.txtQuality;

            try
            {
                if (quality < 0 || quality > 100)
                {
                    throw new Exception();
                }
            }
            catch
            {
                RaiseError("Quality is not a valid number. It should be an integer between 0 and 100.");
                RaiseError("This parameter sets the quality of jpg compression.");
                return;
            }



            var gameConversionManger = Loader.Global.ConversionManager;

            gameConversionManger.CoordSystem = Autodesk.Max.IGameConversionManager.CoordSystem.D3d;

            var gameScene = Loader.Global.IGameInterface;

            if (exportNode == null || exportNode.IsRootNode)
            {
                gameScene.InitialiseIGame(false);
            }
            else
            {
                gameScene.InitialiseIGame(exportNode, true);
            }

            gameScene.SetStaticFrame(0);

            MaxSceneFileName = gameScene.SceneFileName;

            IsCancelled = false;

            string fileExportString = exportNode != null
                ? $"{exportNode.NodeName} | {exportParameters.outputPath}"
                : exportParameters.outputPath;

            RaiseMessage($"Exportation started: {fileExportString}", Color.Blue);
            ReportProgressChanged(0);

            string tempOutputDirectory  = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName());
            string outputDirectory      = Path.GetDirectoryName(exportParameters.outputPath);
            string folderOuputDirectory = exportParameters.textureFolder;
            string outputFileName       = Path.GetFileName(exportParameters.outputPath);

            // Check directory exists
            if (!Directory.Exists(outputDirectory))
            {
                RaiseError("Exportation stopped: Output folder does not exist");
                ReportProgressChanged(100);
                return;
            }
            Directory.CreateDirectory(tempOutputDirectory);

            var outputBabylonDirectory = tempOutputDirectory;

            // Force output file extension to be babylon
            outputFileName = Path.ChangeExtension(outputFileName, "babylon");

            var babylonScene = new BabylonScene(outputBabylonDirectory);

            var rawScene = Loader.Core.RootNode;

            var watch = new Stopwatch();

            watch.Start();

            string outputFormat = exportParameters.outputFormat;

            isBabylonExported = outputFormat == "babylon" || outputFormat == "binary babylon";
            isGltfExported    = outputFormat == "gltf" || outputFormat == "glb";

            // Get scene parameters
            optimizeAnimations = !Loader.Core.RootNode.GetBoolProperty("babylonjs_donotoptimizeanimations");
            exportNonAnimated  = Loader.Core.RootNode.GetBoolProperty("babylonjs_animgroup_exportnonanimated");

            // Save scene
            if (exportParameters.autoSaveSceneFile)
            {
                RaiseMessage("Saving 3ds max file");
                var forceSave = Loader.Core.FileSave;

                callerForm?.BringToFront();
            }

            // Producer
            babylonScene.producer = new BabylonProducer
            {
                name = "3dsmax",
#if MAX2019
                version = "2019",
#elif MAX2018
                version = "2018",
#elif MAX2017
                version = "2017",
#else
                version = Loader.Core.ProductVersion.ToString(),
#endif
                exporter_version = exporterVersion,
                file             = outputFileName
            };

            // Global
            babylonScene.autoClear    = true;
            babylonScene.clearColor   = Loader.Core.GetBackGround(0, Tools.Forever).ToArray();
            babylonScene.ambientColor = Loader.Core.GetAmbient(0, Tools.Forever).ToArray();

            babylonScene.TimelineStartFrame      = Loader.Core.AnimRange.Start / Loader.Global.TicksPerFrame;
            babylonScene.TimelineEndFrame        = Loader.Core.AnimRange.End / Loader.Global.TicksPerFrame;
            babylonScene.TimelineFramesPerSecond = MaxSceneTicksPerSecond / Loader.Global.TicksPerFrame;

            babylonScene.gravity             = rawScene.GetVector3Property("babylonjs_gravity");
            ExportQuaternionsInsteadOfEulers = rawScene.GetBoolProperty("babylonjs_exportquaternions", 1);
            if (string.IsNullOrEmpty(exportParameters.pbrEnvironment) && Loader.Core.UseEnvironmentMap && Loader.Core.EnvironmentMap != null)
            {
                // Environment texture
                var environmentMap = Loader.Core.EnvironmentMap;
                // Copy image file to output if necessary
                var babylonTexture = ExportEnvironmnentTexture(environmentMap, babylonScene);
                if (babylonTexture != null)
                {
                    babylonScene.environmentTexture = babylonTexture.name;

                    // Skybox
                    babylonScene.createDefaultSkybox = rawScene.GetBoolProperty("babylonjs_createDefaultSkybox");
                    babylonScene.skyboxBlurLevel     = rawScene.GetFloatProperty("babylonjs_skyboxBlurLevel");
                }
            }
            else if (!string.IsNullOrEmpty(exportParameters.pbrEnvironment))
            {
                babylonScene.createDefaultSkybox = rawScene.GetBoolProperty("babylonjs_createDefaultSkybox");
                babylonScene.skyboxBlurLevel     = rawScene.GetFloatProperty("babylonjs_skyboxBlurLevel");
            }

            // Instantiate custom material exporters
            materialExporters = new Dictionary <ClassIDWrapper, IMaxMaterialExporter>();
            foreach (Type type in Tools.GetAllLoadableTypes())
            {
                if (type.IsAbstract || type.IsInterface || !typeof(IMaxMaterialExporter).IsAssignableFrom(type))
                {
                    continue;
                }

                IMaxMaterialExporter exporter = Activator.CreateInstance(type) as IMaxMaterialExporter;

                if (exporter == null)
                {
                    RaiseWarning("Creating exporter instance failed: " + type.Name, 1);
                }

                materialExporters.Add(exporter.MaterialClassID, exporter);
            }

            // Sounds
            var soundName = rawScene.GetStringProperty("babylonjs_sound_filename", "");

            if (!string.IsNullOrEmpty(soundName))
            {
                var filename = Path.GetFileName(soundName);

                var globalSound = new BabylonSound
                {
                    autoplay = rawScene.GetBoolProperty("babylonjs_sound_autoplay", 1),
                    loop     = rawScene.GetBoolProperty("babylonjs_sound_loop", 1),
                    name     = filename
                };

                babylonScene.SoundsList.Add(globalSound);

                if (isBabylonExported)
                {
                    try
                    {
                        File.Copy(soundName, Path.Combine(babylonScene.OutputPath, filename), true);
                    }
                    catch
                    {
                    }
                }
            }

            // Root nodes
            RaiseMessage("Exporting nodes");
            HashSet <IIGameNode> maxRootNodes = getRootNodes(gameScene);
            var progressionStep = 80.0f / maxRootNodes.Count;
            var progression     = 10.0f;
            ReportProgressChanged((int)progression);
            referencedMaterials.Clear();
            Tools.guids.Clear();
            // Reseting is optionnal. It makes each morph target manager export starts from id = 0.
            BabylonMorphTargetManager.Reset();
            foreach (var maxRootNode in maxRootNodes)
            {
                BabylonNode node = exportNodeRec(maxRootNode, babylonScene, gameScene);

                // if we're exporting from a specific node, reset the pivot to {0,0,0}
                if (node != null && exportNode != null && !exportNode.IsRootNode)
                {
                    SetNodePosition(ref node, ref babylonScene, new float[] { 0, 0, 0 });
                }

                progression += progressionStep;
                ReportProgressChanged((int)progression);
                CheckCancelled();
            }
            ;
            RaiseMessage(string.Format("Total meshes: {0}", babylonScene.MeshesList.Count), Color.Gray, 1);


            // In 3DS Max the default camera look down (in the -z direction for the 3DS Max reference (+y for babylon))
            // In Babylon the default camera look to the horizon (in the +z direction for the babylon reference)
            // In glTF the default camera look to the horizon (in the +Z direction for glTF reference)
            RaiseMessage("Update camera rotation and position", 1);
            for (int index = 0; index < babylonScene.CamerasList.Count; index++)
            {
                BabylonCamera camera = babylonScene.CamerasList[index];
                FixCamera(ref camera, ref babylonScene);
            }

            // Light for glTF
            if (isGltfExported)
            {
                RaiseMessage("Update light rotation for glTF export", 1);
                for (int index = 0; index < babylonScene.LightsList.Count; index++)
                {
                    BabylonNode light = babylonScene.LightsList[index];
                    FixNodeRotation(ref light, ref babylonScene, -Math.PI / 2);
                }
            }

            // Main camera
            BabylonCamera babylonMainCamera   = null;
            ICameraObject maxMainCameraObject = null;
            if (babylonMainCamera == null && babylonScene.CamerasList.Count > 0)
            {
                // Set first camera as main one
                babylonMainCamera           = babylonScene.CamerasList[0];
                babylonScene.activeCameraID = babylonMainCamera.id;
                RaiseMessage("Active camera set to " + babylonMainCamera.name, Color.Green, 1, true);

                // Retreive camera node with same GUID
                var maxCameraNodesAsTab = gameScene.GetIGameNodeByType(Autodesk.Max.IGameObject.ObjectTypes.Camera);
                var maxCameraNodes      = TabToList(maxCameraNodesAsTab);
                var maxMainCameraNode   = maxCameraNodes.Find(_camera => _camera.MaxNode.GetGuid().ToString() == babylonMainCamera.id);
                maxMainCameraObject = (maxMainCameraNode.MaxNode.ObjectRef as ICameraObject);
            }

            if (babylonMainCamera == null)
            {
                RaiseWarning("No camera defined", 1);
            }
            else
            {
                RaiseMessage(string.Format("Total cameras: {0}", babylonScene.CamerasList.Count), Color.Gray, 1);
            }

            // Default light
            bool addDefaultLight = rawScene.GetBoolProperty("babylonjs_addDefaultLight", 1);
            if (!exportParameters.pbrNoLight && addDefaultLight && babylonScene.LightsList.Count == 0)
            {
                RaiseWarning("No light defined", 1);
                RaiseWarning("A default hemispheric light was added for your convenience", 1);
                ExportDefaultLight(babylonScene);
            }
            else
            {
                RaiseMessage(string.Format("Total lights: {0}", babylonScene.LightsList.Count), Color.Gray, 1);
            }

            if (scaleFactorFloat != 1.0f)
            {
                RaiseMessage("A root node is added for scaling", 1);

                // Create root node for scaling
                BabylonMesh rootNode = new BabylonMesh {
                    name = "root", id = Guid.NewGuid().ToString()
                };
                rootNode.isDummy = true;
                float rootNodeScale = scaleFactorFloat;
                rootNode.scaling = new float[3] {
                    rootNodeScale, rootNodeScale, rootNodeScale
                };

                if (ExportQuaternionsInsteadOfEulers)
                {
                    rootNode.rotationQuaternion = new float[] { 0, 0, 0, 1 };
                }
                else
                {
                    rootNode.rotation = new float[] { 0, 0, 0 };
                }

                // Update all top nodes
                var babylonNodes = new List <BabylonNode>();
                babylonNodes.AddRange(babylonScene.MeshesList);
                babylonNodes.AddRange(babylonScene.CamerasList);
                babylonNodes.AddRange(babylonScene.LightsList);
                foreach (BabylonNode babylonNode in babylonNodes)
                {
                    if (babylonNode.parentId == null)
                    {
                        babylonNode.parentId = rootNode.id;
                    }
                }

                // Store root node
                babylonScene.MeshesList.Add(rootNode);
            }

            // Materials
            if (exportParameters.exportMaterials)
            {
                RaiseMessage("Exporting materials");
                var matsToExport = referencedMaterials.ToArray(); // Snapshot because multimaterials can export new materials
                foreach (var mat in matsToExport)
                {
                    ExportMaterial(mat, babylonScene);
                    CheckCancelled();
                }
                RaiseMessage(string.Format("Total: {0}", babylonScene.MaterialsList.Count + babylonScene.MultiMaterialsList.Count), Color.Gray, 1);
            }
            else
            {
                RaiseMessage("Skipping material export.");
            }

            // Fog
            for (var index = 0; index < Loader.Core.NumAtmospheric; index++)
            {
                var atmospheric = Loader.Core.GetAtmospheric(index);

                if (atmospheric.Active(0) && atmospheric.ClassName == "Fog")
                {
                    var fog = atmospheric as IStdFog;

                    RaiseMessage("Exporting fog");

                    if (fog != null)
                    {
                        babylonScene.fogColor = fog.GetColor(0).ToArray();
                        babylonScene.fogMode  = 3;
                    }
                    if (babylonMainCamera != null)
                    {
                        babylonScene.fogStart = maxMainCameraObject.GetEnvRange(0, 0, Tools.Forever);
                        babylonScene.fogEnd   = maxMainCameraObject.GetEnvRange(0, 1, Tools.Forever);
                    }
                }
            }

            // Skeletons
            if (skins.Count > 0)
            {
                RaiseMessage("Exporting skeletons");
                foreach (var skin in skins)
                {
                    ExportSkin(skin, babylonScene);
                }
            }

            // ----------------------------
            // ----- Animation groups -----
            // ----------------------------
            RaiseMessage("Export animation groups");
            // add animation groups to the scene
            babylonScene.animationGroups = ExportAnimationGroups(babylonScene);

            if (isBabylonExported)
            {
                // if we are exporting to .Babylon then remove then remove animations from nodes if there are animation groups.
                if (babylonScene.animationGroups.Count > 0)
                {
                    foreach (BabylonNode node in babylonScene.MeshesList)
                    {
                        node.animations = null;
                    }
                    foreach (BabylonNode node in babylonScene.LightsList)
                    {
                        node.animations = null;
                    }
                    foreach (BabylonNode node in babylonScene.CamerasList)
                    {
                        node.animations = null;
                    }
                    foreach (BabylonSkeleton skel in babylonScene.SkeletonsList)
                    {
                        foreach (BabylonBone bone in skel.bones)
                        {
                            bone.animation = null;
                        }
                    }
                }

                // setup a default skybox for the scene for .Babylon export.
                var sourcePath = exportParameters.pbrEnvironment;
                if (!string.IsNullOrEmpty(sourcePath))
                {
                    var fileName = Path.GetFileName(sourcePath);

                    // Allow only dds file format
                    if (!fileName.EndsWith(".dds"))
                    {
                        RaiseWarning("Failed to export defauenvironment texture: only .dds format is supported.");
                    }
                    else
                    {
                        RaiseMessage($"texture id = Max_Babylon_Default_Environment");
                        babylonScene.environmentTexture = fileName;

                        if (exportParameters.writeTextures)
                        {
                            try
                            {
                                var destPath = Path.Combine(babylonScene.OutputPath, fileName);
                                if (File.Exists(sourcePath) && sourcePath != destPath)
                                {
                                    File.Copy(sourcePath, destPath, true);
                                }
                            }
                            catch
                            {
                                // silently fails
                                RaiseMessage($"Fail to export the default env texture", 3);
                            }
                        }
                    }
                }
            }


            // Output
            babylonScene.Prepare(false, false);
            if (isBabylonExported)
            {
                RaiseMessage("Saving to output file");

                var outputFile = Path.Combine(outputBabylonDirectory, outputFileName);

                var jsonSerializer = JsonSerializer.Create(new JsonSerializerSettings());
                var sb             = new StringBuilder();
                var sw             = new StringWriter(sb, CultureInfo.InvariantCulture);
                using (var jsonWriter = new JsonTextWriterOptimized(sw))
                {
                    jsonWriter.Formatting = Formatting.None;
                    jsonSerializer.Serialize(jsonWriter, babylonScene);
                }
                File.WriteAllText(outputFile, sb.ToString());

                if (exportParameters.generateManifest)
                {
                    File.WriteAllText(outputFile + ".manifest",
                                      "{\r\n\"version\" : 1,\r\n\"enableSceneOffline\" : true,\r\n\"enableTexturesOffline\" : true\r\n}");
                }

                // Binary
                if (outputFormat == "binary babylon")
                {
                    RaiseMessage("Generating binary files");
                    BabylonFileConverter.BinaryConverter.Convert(outputFile, outputBabylonDirectory + "\\Binary",
                                                                 message => RaiseMessage(message, 1),
                                                                 error => RaiseError(error, 1));
                }
            }

            ReportProgressChanged(100);

            // Export glTF
            if (isGltfExported)
            {
                bool generateBinary = outputFormat == "glb";

                GLTFExporter gltfExporter = new GLTFExporter();
                exportParameters.customGLTFMaterialExporter = new MaxGLTFMaterialExporter(exportParameters, gltfExporter, this);
                gltfExporter.ExportGltf(this.exportParameters, babylonScene, tempOutputDirectory, outputFileName, generateBinary, this);
            }
            // Move files to output directory
            var filePaths = Directory.GetFiles(tempOutputDirectory);
            if (outputFormat == "binary babylon")
            {
                var tempBinaryOutputDirectory = Path.Combine(tempOutputDirectory, "Binary");
                var binaryFilePaths           = Directory.GetFiles(tempBinaryOutputDirectory);
                foreach (var filePath in binaryFilePaths)
                {
                    if (filePath.EndsWith(".binary.babylon"))
                    {
                        var file         = Path.GetFileName(filePath);
                        var tempFilePath = Path.Combine(tempBinaryOutputDirectory, file);
                        var outputFile   = Path.Combine(outputDirectory, file);

                        IUTF8Str maxNotification = GlobalInterface.Instance.UTF8Str.Create(outputFile);
                        Loader.Global.BroadcastNotification(SystemNotificationCode.PreExport, maxNotification);
                        moveFileToOutputDirectory(tempFilePath, outputFile, exportParameters);
                        Loader.Global.BroadcastNotification(SystemNotificationCode.PostExport, maxNotification);
                    }
                    else if (filePath.EndsWith(".babylonbinarymeshdata"))
                    {
                        var file         = Path.GetFileName(filePath);
                        var tempFilePath = Path.Combine(tempBinaryOutputDirectory, file);
                        var outputFile   = Path.Combine(outputDirectory, file);

                        IUTF8Str maxNotification = GlobalInterface.Instance.UTF8Str.Create(outputFile);
                        Loader.Global.BroadcastNotification(SystemNotificationCode.PreExport, maxNotification);
                        moveFileToOutputDirectory(tempFilePath, outputFile, exportParameters);
                        Loader.Global.BroadcastNotification(SystemNotificationCode.PostExport, maxNotification);
                    }
                }
            }
            if (outputFormat == "glb")
            {
                foreach (var file_path in filePaths)
                {
                    if (Path.GetExtension(file_path) == ".glb")
                    {
                        var file         = Path.GetFileName(file_path);
                        var tempFilePath = Path.Combine(tempOutputDirectory, file);
                        var outputFile   = Path.Combine(outputDirectory, file);


                        IUTF8Str maxNotification = GlobalInterface.Instance.UTF8Str.Create(outputFile);
                        Loader.Global.BroadcastNotification(SystemNotificationCode.PreExport, maxNotification);
                        moveFileToOutputDirectory(tempFilePath, outputFile, exportParameters);
                        Loader.Global.BroadcastNotification(SystemNotificationCode.PostExport, maxNotification);

                        break;
                    }
                }
            }
            else
            {
                foreach (var filePath in filePaths)
                {
                    var    file         = Path.GetFileName(filePath);
                    string ext          = Path.GetExtension(file);
                    var    tempFilePath = Path.Combine(tempOutputDirectory, file);
                    var    outputPath   = Path.Combine(outputDirectory, file);
                    if (!string.IsNullOrWhiteSpace(exportParameters.textureFolder) && TextureUtilities.ExtensionIsValidGLTFTexture(ext))
                    {
                        outputPath = Path.Combine(exportParameters.textureFolder, file);
                    }

                    IUTF8Str maxNotification = GlobalInterface.Instance.UTF8Str.Create(outputPath);
                    Loader.Global.BroadcastNotification(SystemNotificationCode.PreExport, maxNotification);
                    moveFileToOutputDirectory(tempFilePath, outputPath, exportParameters);
                    Loader.Global.BroadcastNotification(SystemNotificationCode.PostExport, maxNotification);
                }
            }
            Directory.Delete(tempOutputDirectory, true);
            watch.Stop();

            RaiseMessage(string.Format("Exportation done in {0:0.00}s: {1}", watch.ElapsedMilliseconds / 1000.0, fileExportString), Color.Blue);
            IUTF8Str max_notification = Autodesk.Max.GlobalInterface.Instance.UTF8Str.Create("BabylonExportComplete");
            Loader.Global.BroadcastNotification(SystemNotificationCode.PostExport, max_notification);
        }
Пример #24
0
        private GLTFTextureInfo ExportTexture(BabylonTexture babylonTexture, GLTF gltf, string name)
        {
            if (babylonTexture == null)
            {
                return(null);
            }

            if (name == null)
            {
                name = babylonTexture.name;
            }

            logger.RaiseMessage("GLTFExporter.Texture | Export texture named: " + name, 2);

            if (glTFTextureInfoMap.ContainsKey(babylonTexture.Id))
            {
                return(glTFTextureInfoMap[babylonTexture.Id]);
            }
            else
            {
                var sourcePath = babylonTexture.originalPath;
                if (babylonTexture.bitmap != null)
                {
                    sourcePath = Path.Combine(gltf.OutputFolder, name);
                }

                if (sourcePath == null || sourcePath == "")
                {
                    logger.RaiseWarning("Texture path is missing.", 3);
                    return(null);
                }

                var validImageFormat = TextureUtilities.GetValidImageFormat(Path.GetExtension(sourcePath));

                if (validImageFormat == null)
                {
                    // Image format is not supported by the exporter
                    logger.RaiseWarning(string.Format("Format of texture {0} is not supported by the exporter. Consider using a standard image format like jpg or png.", Path.GetFileName(sourcePath)), 3);
                    return(null);
                }

                var destPath = Path.Combine(gltf.OutputFolder, name);
                destPath = Path.ChangeExtension(destPath, validImageFormat);

                name = Path.ChangeExtension(name, validImageFormat);

                // --------------------------
                // -------- Sampler ---------
                // --------------------------
                logger.RaiseMessage("GLTFExporter.Texture | create sampler", 3);
                GLTFSampler gltfSampler = new GLTFSampler();
                gltfSampler.index = gltf.SamplersList.Count;

                // --- Retrieve info from babylon texture ---
                // Mag and min filters
                GLTFSampler.TextureMagFilter?magFilter;
                GLTFSampler.TextureMinFilter?minFilter;
                getSamplingParameters(babylonTexture.samplingMode, out magFilter, out minFilter);
                gltfSampler.magFilter = magFilter;
                gltfSampler.minFilter = minFilter;
                // WrapS and wrapT
                gltfSampler.wrapS = getWrapMode(babylonTexture.wrapU);
                gltfSampler.wrapT = getWrapMode(babylonTexture.wrapV);

                var matchingSampler = gltf.SamplersList.FirstOrDefault(sampler => sampler.wrapS == gltfSampler.wrapS && sampler.wrapT == gltfSampler.wrapT && sampler.magFilter == gltfSampler.magFilter && sampler.minFilter == gltfSampler.minFilter);
                if (matchingSampler != null)
                {
                    gltfSampler = matchingSampler;
                }
                else
                {
                    gltf.SamplersList.Add(gltfSampler);
                }


                // --------------------------
                // --------- Image ----------
                // --------------------------

                logger.RaiseMessage("GLTFExporter.Texture | create image", 3);
                GLTFImage gltfImage = null;
                if (glTFImageMap.ContainsKey(name))
                {
                    gltfImage = glTFImageMap[name];
                }
                else
                {
                    string textureUri = name;
                    if (!string.IsNullOrWhiteSpace(exportParameters.textureFolder))
                    {
                        textureUri = PathUtilities.GetRelativePath(exportParameters.outputPath, exportParameters.textureFolder);
                        textureUri = Path.Combine(textureUri, name);
                    }
                    gltfImage = new GLTFImage
                    {
                        uri = textureUri
                    };
                    gltfImage.index = gltf.ImagesList.Count;
                    gltf.ImagesList.Add(gltfImage);
                    switch (validImageFormat)
                    {
                    case "jpg":
                        gltfImage.FileExtension = "jpeg";
                        break;

                    case "png":
                        gltfImage.FileExtension = "png";
                        break;
                    }
                    if (exportParameters.outputFormat == "glb")
                    {
                        var imageBufferView = WriteImageToGltfBuffer(gltf, gltfImage, sourcePath, babylonTexture.bitmap);
                        gltfImage.uri        = null;
                        gltfImage.bufferView = imageBufferView.index;
                        gltfImage.mimeType   = "image/" + gltfImage.FileExtension;
                    }
                    else
                    {
                        if (exportParameters.writeTextures)
                        {
                            if (babylonTexture.bitmap != null)
                            {
                                // We may have modified this texture image, copy the buffer contents to disk
                                var extension   = Path.GetExtension(name).ToLower();
                                var imageFormat = extension == ".jpg" ? System.Drawing.Imaging.ImageFormat.Jpeg : System.Drawing.Imaging.ImageFormat.Png;
                                logger.RaiseMessage($"GLTFExporter.Texture | write image '{name}' to '{destPath}'", 3);
                                TextureUtilities.SaveBitmap(babylonTexture.bitmap, destPath, imageFormat, exportParameters.txtQuality, logger);
                            }
                            else
                            {
                                // Copy texture from source to output
                                TextureUtilities.CopyTexture(sourcePath, destPath, exportParameters.txtQuality, logger);
                            }
                        }
                    }
                    glTFImageMap.Add(name, gltfImage);
                }

                // --------------------------
                // -------- Texture ---------
                // --------------------------

                logger.RaiseMessage("GLTFExporter.Texture | create texture", 3);
                var gltfTexture = new GLTFTexture
                {
                    name    = name,
                    sampler = gltfSampler.index,
                    source  = gltfImage.index
                };
                gltfTexture.index = gltf.TexturesList.Count;

                if (!CheckIfImageIsRegistered(name))
                {
                    gltf.TexturesList.Add(gltfTexture);
                }
                else
                {
                    gltfTexture = gltf.TexturesList[GetRegisteredTexture(gltfTexture.name).index];
                }

                // --------------------------
                // ------ TextureInfo -------
                // --------------------------
                var gltfTextureInfo = new GLTFTextureInfo
                {
                    index    = gltfTexture.index,
                    texCoord = babylonTexture.coordinatesIndex
                };

                if (!(babylonTexture.uOffset == 0) || !(babylonTexture.vOffset == 0) || !(babylonTexture.uScale == 1) || !(babylonTexture.vScale == 1) || !(babylonTexture.wAng == 0))
                {
                    // Add texture extension if enabled in the export settings
                    if (exportParameters.enableKHRTextureTransform)
                    {
                        AddTextureTransformExtension(ref gltf, ref gltfTextureInfo, babylonTexture);
                    }
                    else
                    {
                        logger.RaiseWarning("GLTFExporter.Texture | KHR_texture_transform is not enabled, so the texture may look incorrect at runtime!", 3);
                        logger.RaiseWarning("GLTFExporter.Texture | KHR_texture_transform is not enabled, so the texture may look incorrect at runtime!", 3);
                    }
                }
                var textureID = name + TextureTransformID(gltfTextureInfo);
                // Check for texture optimization.  This is done here after the texture transform has been potentially applied to the texture extension
                if (CheckIfImageIsRegistered(textureID))
                {
                    var textureComponent = GetRegisteredTexture(textureID);

                    return(textureComponent);
                }

                // Add the texture in the dictionary
                RegisterTexture(gltfTextureInfo, textureID);
                glTFTextureInfoMap[babylonTexture.Id] = gltfTextureInfo;

                return(gltfTextureInfo);
            }
        }
Пример #25
0
    private void GeneratePackedTexture()
    {
        var redChannelInput   = _channelRedTextureObjectField.value;
        var greenChannelInput = _channelGreenTextureObjectField.value;
        var blueChannelInput  = _channelBlueTextureObjectField.value;
        var alphaChannelInput = _channelAlphaTextureObjectField.value;
        var width             = _widthIntField.value;
        var height            = _heightIntField.value;

        var redChannelTexture   = (Texture2D)redChannelInput;
        var greenChannelTexture = (Texture2D)greenChannelInput;
        var blueChannelTexture  = (Texture2D)blueChannelInput;
        var alphaChannelTexture = (Texture2D)alphaChannelInput;

        // Create the composite texture
        Texture2D compositeTexture;

        if (_scaleToSpecificValueToggle.value)
        {
            compositeTexture = TexturePacker.GetCompositeTextureRgb(
                _nameIdentifierTextField.text,
                redChannelTexture,
                greenChannelTexture,
                blueChannelTexture,
                alphaChannelTexture,
                (int)_textureSizeVectorField.value.x,
                (int)_textureSizeVectorField.value.y);
        }
        else
        {
            compositeTexture = TexturePacker.GetCompositeTextureRgb(
                _nameIdentifierTextField.text,
                redChannelTexture,
                greenChannelTexture,
                blueChannelTexture,
                alphaChannelTexture);
        }

        // If inputs are valid, add their names to a list
        var validInputsNameList = new List <string>();

        if (redChannelTexture)
        {
            validInputsNameList.Add(redChannelTexture.name);
        }
        if (greenChannelTexture)
        {
            validInputsNameList.Add(greenChannelTexture.name);
        }
        if (blueChannelTexture)
        {
            validInputsNameList.Add(blueChannelTexture.name);
        }
        if (alphaChannelTexture)
        {
            validInputsNameList.Add(alphaChannelTexture.name);
        }

        // Find the common substring in the names and add the identifier
        var compositeTextureName = StringUtilities.GetCommonPrefix(validInputsNameList) + _nameIdentifierTextField.text;

        // Find the first valid input and create the path based on that
        var listOfTextureInputs = new List <Texture2D>()
        {
            redChannelTexture,
            redChannelTexture,
            redChannelTexture,
            alphaChannelTexture
        };
        var relativeCompositeTexturePath =
            Path.Combine(
                Path.GetDirectoryName(AssetDatabase.GetAssetPath(
                                          GetFirstValidTextureInput(listOfTextureInputs))),
                compositeTextureName);

        // Save the composite texture
        var hasSaved = false;

        if (_tgaToggle.value)
        {
            var newRelativeCompositeTexturePath = relativeCompositeTexturePath + _tgaToggle.label;
            var absoluteCompositeTexturePath    = Path.Combine(
                Directory.GetParent(Application.dataPath).FullName,
                newRelativeCompositeTexturePath);
            TextureUtilities.SaveTextureToPath(
                compositeTexture,
                absoluteCompositeTexturePath,
                TextureUtilities.TextureUtilitiesFormats.Tga);
            hasSaved = true;
        }
        if (_pngToggle.value)
        {
            var newRelativeCompositeTexturePath = relativeCompositeTexturePath + _pngToggle.label;
            var absoluteCompositeTexturePath    = Path.Combine(
                Directory.GetParent(Application.dataPath).FullName,
                newRelativeCompositeTexturePath);
            TextureUtilities.SaveTextureToPath(
                compositeTexture,
                absoluteCompositeTexturePath,
                TextureUtilities.TextureUtilitiesFormats.Png);
            hasSaved = true;
        }

        // Update the previews for the provided images
        _previewImageRedChannelVisualElement.style.backgroundImage   = redChannelTexture;
        _previewImageGreenChannelVisualElement.style.backgroundImage = greenChannelTexture;
        _previewImageBlueChannelVisualElement.style.backgroundImage  = blueChannelTexture;
        _previewImageAlphaChannelVisualElement.style.backgroundImage = alphaChannelTexture;

        // If a new texture has been saved to disk, display it and select in the Project Window
        if (hasSaved)
        {
            AssetDatabase.Refresh();
            compositeTexture.Apply();
            _previewImageResultVisualElement.style.backgroundImage = compositeTexture;
            Selection.activeObject = AssetDatabase.LoadAssetAtPath(relativeCompositeTexturePath, typeof(Texture2D));
        }
    }
Пример #26
0
        /// <returns></returns>
        private BabylonTexture ExportBaseColorAlphaTexture(ITexmap baseColorTexMap, ITexmap alphaTexMap, float[] baseColor, float alpha, BabylonScene babylonScene, string materialName, bool isOpacity = false)
        {
            // --- Babylon texture ---
            var    baseColorTexture             = _getBitmapTex(baseColorTexMap);
            var    alphaTexture                 = _getBitmapTex(alphaTexMap);
            string baseColorTextureMapExtension = null;

            // If we don't retrieve any textures from Max, return null.
            if (baseColorTexture == null && alphaTexture == null)
            {
                return(null);
            }

            // If we only have a base color texture, and we are using an opaque texture, export the base color image only.
            if (baseColorTexture != null && alphaTexture == null)
            {
                baseColorTextureMapExtension = Path.GetExtension(baseColorTexture.Map.FullFilePath).ToLower();
                if (alpha == 1)
                {
                    if (baseColorTexture.AlphaSource == MaxConstants.IMAGE_ALPHA_FILE &&
                        (baseColorTextureMapExtension == ".tif" || baseColorTextureMapExtension == ".tiff"))
                    {
                        RaiseWarning($"Diffuse texture named {baseColorTexture.Map.FullFilePath} is a .tif file and its Alpha Source is 'Image Alpha' by default.", 3);
                        RaiseWarning($"If you don't want material to be in BLEND mode, set diffuse texture Alpha Source to 'None (Opaque)'", 3);
                    }

                    // Copy base color image
                    var outTexture = ExportTexture(baseColorTexture, babylonScene);
                    textureMap[outTexture.Id] = outTexture;
                    return(outTexture);
                }
            }

            // Otherwise combine base color and alpha textures to a single output texture
            RaiseMessage("Export baseColor+Alpha texture", 2);

            var hasBaseColor = baseColorTexture != null && isTextureOk(baseColorTexMap);
            var hasAlpha     = isTextureOk(alphaTexMap);
            var texture      = hasBaseColor ? baseColorTexture : alphaTexture;

            ImageFormat imageFormat = null;

            if (hasBaseColor)
            {
                imageFormat = TextureUtilities.GetImageFormat(Path.GetExtension(baseColorTexture.Map.FullFilePath));
            }

            if (hasAlpha || imageFormat == null)
            {
                baseColorTextureMapExtension = ".png"; // since we are adding an alpha channel, export as png. This will convert any other input base texture format to PNG.
                imageFormat = ImageFormat.Png;
            }

            // since we are creating a new texture, give it a unique ID based on the base color and alpha maps.
            var nameText  = (hasBaseColor ? Path.GetFileNameWithoutExtension(baseColorTexture.Map.FullFilePath) + (hasAlpha ?  "_" + Path.GetFileNameWithoutExtension(alphaTexture.Map.FullFilePath) : "") : TextureUtilities.ColorToStringName(baseColor));
            var textureID = hasBaseColor ? texture.GetGuid().ToString() + (hasAlpha ? "_" + alphaTexture.GetGuid().ToString() : "") : string.Format("{0}_{1}", texture.GetGuid().ToString(), nameText);

            if (textureMap.ContainsKey(textureID))
            {
                return(textureMap[textureID]);
            }

            BabylonTexture babylonTexture = null;

            babylonTexture = new BabylonTexture(textureID)
            {
                name = nameText
            };

            // Alpha
            babylonTexture.hasAlpha        = hasAlpha || (hasBaseColor && (baseColorTexture.AlphaSource == MaxConstants.IMAGE_ALPHA_FILE || baseColorTexture.AlphaSource == MaxConstants.IMAGE_ALPHA_RGB)) || alpha < 1.0f;
            babylonTexture.getAlphaFromRGB = false;

            if (!hasBaseColor && !hasAlpha)
            {
                return(null);
            }

            if ((!isTextureOk(alphaTexMap) && alpha == 1.0f && (isTextureOk(baseColorTexMap) && baseColorTexture.AlphaSource == MaxConstants.IMAGE_ALPHA_FILE)) &&
                (baseColorTextureMapExtension == ".tif" || baseColorTextureMapExtension == ".tiff"))
            {
                RaiseWarning($"Diffuse texture named {baseColorTexture.Map.FullFilePath} is a .tif file and its Alpha Source is 'Image Alpha' by default.", 3);
                RaiseWarning($"If you don't want material to be in BLEND mode, set diffuse texture Alpha Source to 'None (Opaque)'", 3);
            }

            // Set image format

            if (hasAlpha)
            {
                babylonTexture.name += "_alpha_" + alphaTexture.Name;
            }

            if (imageFormat == ImageFormat.Jpeg)
            {
                babylonTexture.name += ".jpg";
            }
            else
            {
                babylonTexture.name += "." + imageFormat.ToString();
            }

            // Level
            babylonTexture.level = 1.0f;

            // UVs
            var uvGen = _exportUV(texture.UVGen, babylonTexture);

            // Is cube
            _exportIsCube(texture.Map.FullFilePath, babylonTexture, false);

            // --- Merge baseColor and alpha maps ---

            if (exportParameters.writeTextures && baseColorTexture != alphaTexture && alphaTexture != null)
            {
                // Load bitmaps
                var baseColorBitmap = _loadTexture(baseColorTexMap);
                var alphaBitmap     = _loadTexture(alphaTexMap);

                // Retreive dimensions
                int width              = 0;
                int height             = 0;
                var haveSameDimensions = TextureUtilities.GetMinimalBitmapDimensions(out width, out height, baseColorBitmap, alphaBitmap);
                if (!haveSameDimensions)
                {
                    RaiseError("Base color and transparency color maps should have same dimensions", 3);
                }

                var getAlphaFromRGB = alphaTexture != null && ((alphaTexture.AlphaSource == MaxConstants.IMAGE_ALPHA_RGB) || (alphaTexture.AlphaSource == MaxConstants.IMAGE_ALPHA_NONE)); // 'RGB intensity' or 'None (Opaque)'

                // Create baseColor+alpha map
                var _baseColor = Color.FromArgb(
                    (int)(baseColor[0] * 255),
                    (int)(baseColor[1] * 255),
                    (int)(baseColor[2] * 255));
                var    _alpha = (int)(alpha * 255);
                Bitmap baseColorAlphaBitmap = new Bitmap(width, height);
                for (int x = 0; x < width; x++)
                {
                    for (int y = 0; y < height; y++)
                    {
                        var baseColorAtPixel = baseColorBitmap != null?baseColorBitmap.GetPixel(x, y) : _baseColor;

                        Color baseColorAlpha;
                        if (alphaBitmap != null)
                        {
                            // Retreive alpha from alpha texture
                            Color alphaColor   = alphaBitmap.GetPixel(x, y);
                            int   alphaAtPixel = getAlphaFromRGB ? alphaColor.R : alphaColor.A;
                            if (isOpacity == false)
                            {
                                // Convert transparency to opacity
                                alphaAtPixel = 255 - alphaAtPixel;
                            }
                            baseColorAlpha = Color.FromArgb(alphaAtPixel, baseColorAtPixel);
                        }
                        else if (baseColorTexture != null && baseColorTexture.AlphaSource == MaxConstants.IMAGE_ALPHA_FILE) // Alpha source is 'Image Alpha'
                        {
                            // Use all channels from base color
                            baseColorAlpha = baseColorAtPixel;
                        }
                        else
                        {
                            // Use RGB channels from base color and default alpha
                            baseColorAlpha = Color.FromArgb(_alpha, baseColorAtPixel.R, baseColorAtPixel.G, baseColorAtPixel.B);
                        }
                        baseColorAlphaBitmap.SetPixel(x, y, baseColorAlpha);
                    }
                }

                // Write bitmap
                if (isBabylonExported)
                {
                    RaiseMessage($"Texture | write image '{babylonTexture.name}'", 3);
                    TextureUtilities.SaveBitmap(baseColorAlphaBitmap, babylonScene.OutputPath, babylonTexture.name, imageFormat, exportParameters.txtQuality, this);
                }
                else
                {
                    // Store created bitmap for further use in gltf export
                    babylonTexture.bitmap = baseColorAlphaBitmap;
                }
            }

            return(babylonTexture);
        }
 private string GetGltfValidImageFormat(string extension)
 {
     return(TextureUtilities.GetValidImageFormat(extension));
 }
Пример #28
0
        private void ExportMaterial(BabylonMaterial babylonMaterial, GLTF gltf)
        {
            var name = babylonMaterial.name;
            var id   = babylonMaterial.id;

            logger.RaiseMessage("GLTFExporter.Material | Export material named: " + name, 1);

            GLTFMaterial          gltfMaterial           = null;
            string                message                = null;
            IGLTFMaterialExporter customMaterialExporter = exportParameters.customGLTFMaterialExporter;

            if (customMaterialExporter != null && customMaterialExporter.GetGltfMaterial(babylonMaterial, gltf, logger, out gltfMaterial))
            {
                gltfMaterial.index = gltf.MaterialsList.Count;
                gltf.MaterialsList.Add(gltfMaterial);
            }
            else if (babylonMaterial.GetType() == typeof(BabylonStandardMaterial))
            {
                var babylonStandardMaterial = babylonMaterial as BabylonStandardMaterial;


                // --- prints ---
                #region prints

                logger.RaiseVerbose("GLTFExporter.Material | babylonMaterial data", 2);
                logger.RaiseVerbose("GLTFExporter.Material | babylonMaterial.alpha=" + babylonMaterial.alpha, 3);
                logger.RaiseVerbose("GLTFExporter.Material | babylonMaterial.alphaMode=" + babylonMaterial.alphaMode, 3);
                logger.RaiseVerbose("GLTFExporter.Material | babylonMaterial.backFaceCulling=" + babylonMaterial.backFaceCulling, 3);
                logger.RaiseVerbose("GLTFExporter.Material | babylonMaterial.wireframe=" + babylonMaterial.wireframe, 3);

                // Ambient
                for (int i = 0; i < babylonStandardMaterial.ambient.Length; i++)
                {
                    logger.RaiseVerbose("GLTFExporter.Material | babylonStandardMaterial.ambient[" + i + "]=" + babylonStandardMaterial.ambient[i], 3);
                }

                // Diffuse
                logger.RaiseVerbose("GLTFExporter.Material | babylonStandardMaterial.diffuse.Length=" + babylonStandardMaterial.diffuse.Length, 3);
                for (int i = 0; i < babylonStandardMaterial.diffuse.Length; i++)
                {
                    logger.RaiseVerbose("GLTFExporter.Material | babylonStandardMaterial.diffuse[" + i + "]=" + babylonStandardMaterial.diffuse[i], 3);
                }
                if (babylonStandardMaterial.diffuseTexture == null)
                {
                    logger.RaiseVerbose("GLTFExporter.Material | babylonStandardMaterial.diffuseTexture=null", 3);
                }
                else
                {
                    logger.RaiseVerbose("GLTFExporter.Material | babylonStandardMaterial.diffuseTexture.name=" + babylonStandardMaterial.diffuseTexture.name, 3);
                }

                // Normal / bump
                if (babylonStandardMaterial.bumpTexture == null)
                {
                    logger.RaiseVerbose("GLTFExporter.Material | babylonStandardMaterial.bumpTexture=null", 3);
                }
                else
                {
                    logger.RaiseVerbose("GLTFExporter.Material | babylonStandardMaterial.bumpTexture.name=" + babylonStandardMaterial.bumpTexture.name, 3);
                }

                // Opacity
                if (babylonStandardMaterial.opacityTexture == null)
                {
                    logger.RaiseVerbose("GLTFExporter.Material | babylonStandardMaterial.opacityTexture=null", 3);
                }
                else
                {
                    logger.RaiseVerbose("GLTFExporter.Material | babylonStandardMaterial.opacityTexture.name=" + babylonStandardMaterial.opacityTexture.name, 3);
                }

                // Specular
                for (int i = 0; i < babylonStandardMaterial.specular.Length; i++)
                {
                    logger.RaiseVerbose("GLTFExporter.Material | babylonStandardMaterial.specular[" + i + "]=" + babylonStandardMaterial.specular[i], 3);
                }
                logger.RaiseVerbose("GLTFExporter.Material | babylonStandardMaterial.specularPower=" + babylonStandardMaterial.specularPower, 3);
                if (babylonStandardMaterial.specularTexture == null)
                {
                    logger.RaiseVerbose("GLTFExporter.Material | babylonStandardMaterial.specularTexture=null", 3);
                }
                else
                {
                    logger.RaiseVerbose("GLTFExporter.Material | babylonStandardMaterial.specularTexture.name=" + babylonStandardMaterial.specularTexture.name, 3);
                }

                // Occlusion
                if (babylonStandardMaterial.ambientTexture == null)
                {
                    logger.RaiseVerbose("GLTFExporter.Material | babylonStandardMaterial.ambientTexture=null", 3);
                }
                else
                {
                    logger.RaiseVerbose("GLTFExporter.Material | babylonStandardMaterial.ambientTexture.name=" + babylonStandardMaterial.ambientTexture.name, 3);
                }

                // Emissive
                for (int i = 0; i < babylonStandardMaterial.emissive.Length; i++)
                {
                    logger.RaiseVerbose("GLTFExporter.Material | babylonStandardMaterial.emissive[" + i + "]=" + babylonStandardMaterial.emissive[i], 3);
                }
                if (babylonStandardMaterial.emissiveTexture == null)
                {
                    logger.RaiseVerbose("GLTFExporter.Material | babylonStandardMaterial.emissiveTexture=null", 3);
                }
                else
                {
                    logger.RaiseVerbose("GLTFExporter.Material | babylonStandardMaterial.emissiveTexture.name=" + babylonStandardMaterial.emissiveTexture.name, 3);
                }
                #endregion


                // --------------------------------
                // --------- gltfMaterial ---------
                // --------------------------------

                logger.RaiseMessage("GLTFExporter.Material | create gltfMaterial", 2);
                gltfMaterial = new GLTFMaterial
                {
                    name = name
                };
                gltfMaterial.id    = babylonMaterial.id;
                gltfMaterial.index = gltf.MaterialsList.Count;
                gltf.MaterialsList.Add(gltfMaterial);

                // Alpha
                string alphaMode;
                float? alphaCutoff;
                getAlphaMode(babylonStandardMaterial, out alphaMode, out alphaCutoff);
                gltfMaterial.alphaMode   = alphaMode;
                gltfMaterial.alphaCutoff = alphaCutoff;

                // DoubleSided
                gltfMaterial.doubleSided = !babylonMaterial.backFaceCulling;

                // Normal
                gltfMaterial.normalTexture = ExportTexture(babylonStandardMaterial.bumpTexture, gltf);

                // Occulison
                gltfMaterial.occlusionTexture = ExportTexture(babylonStandardMaterial.ambientTexture, gltf);

                // Emissive
                gltfMaterial.emissiveFactor = babylonStandardMaterial.emissive;
                // linkEmissiveWithDiffuse attribute doesn't have an equivalent in gltf format
                // When true, the emissive texture needs to be manually multiplied with diffuse texture
                // Otherwise, the emissive texture is assumed to be already pre-multiplied
                if (babylonStandardMaterial.linkEmissiveWithDiffuse)
                {
                    // Even when no emissive texture is provided, the self illumination value needs to be multiplied to the diffuse texture in order to get the pre-multiplied emissive (texture)
                    if (babylonStandardMaterial.emissiveTexture != null || babylonStandardMaterial.selfIllum > 0)
                    {
                        // Default emissive is the raw value of the self illumination
                        // It is not the babylon emissive value which is already pre-multiplied with diffuse color
                        float[] defaultEmissive = new float[] { 1, 1, 1 }.Multiply(babylonStandardMaterial.selfIllum);
                        gltfMaterial.emissiveTexture = ExportEmissiveTexture(babylonStandardMaterial, gltf, defaultEmissive, babylonStandardMaterial.diffuse);
                    }
                }
                else
                {
                    gltfMaterial.emissiveTexture = ExportTexture(babylonStandardMaterial.emissiveTexture, gltf);
                }

                // Constraints
                if (gltfMaterial.emissiveTexture != null)
                {
                    gltfMaterial.emissiveFactor = new[] { 1.0f, 1.0f, 1.0f };
                }

                // --------------------------------
                // --- gltfPbrMetallicRoughness ---
                // --------------------------------

                logger.RaiseMessage("GLTFExporter.Material | create gltfPbrMetallicRoughness", 2);
                var gltfPbrMetallicRoughness = new GLTFPBRMetallicRoughness();
                gltfMaterial.pbrMetallicRoughness = gltfPbrMetallicRoughness;

                // --- Global ---

                // Eye Ball correction to limit overall brightness from std to PBR.
                // This only impacts the factors.
                var correctedDiffuse = new BabylonColor3(babylonStandardMaterial.diffuse).scale(0.5f);

                SpecularGlossiness _specularGlossiness = new SpecularGlossiness
                {
                    diffuse    = correctedDiffuse,
                    opacity    = babylonMaterial.alpha,
                    specular   = new BabylonColor3(babylonStandardMaterial.specular),
                    glossiness = babylonStandardMaterial.specularPower / 256
                };

                MetallicRoughness _metallicRoughness = ConvertToMetallicRoughness(_specularGlossiness, true);

                // Base color
                gltfPbrMetallicRoughness.baseColorFactor = new float[4]
                {
                    _metallicRoughness.baseColor.r,
                    _metallicRoughness.baseColor.g,
                    _metallicRoughness.baseColor.b,
                    _metallicRoughness.opacity
                };

                // Metallic roughness
                gltfPbrMetallicRoughness.metallicFactor  = _metallicRoughness.metallic;
                gltfPbrMetallicRoughness.roughnessFactor = _metallicRoughness.roughness;


                // --- Textures ---
                var babylonTexture = babylonStandardMaterial.diffuseTexture != null ? babylonStandardMaterial.diffuseTexture :
                                     babylonStandardMaterial.specularTexture != null ? babylonStandardMaterial.specularTexture :
                                     babylonStandardMaterial.opacityTexture != null ? babylonStandardMaterial.opacityTexture :
                                     null;

                if (babylonTexture != null)
                {
                    //Check if the texture already exist
                    var _key = SetStandText(babylonStandardMaterial);

                    if (GetStandTextInfo(_key) != null)
                    {
                        var _pairBCMR = GetStandTextInfo(_key);
                        gltfPbrMetallicRoughness.baseColorTexture         = _pairBCMR.baseColor;
                        gltfPbrMetallicRoughness.metallicRoughnessTexture = _pairBCMR.metallicRoughness;
                    }
                    else
                    {
                        bool isAlphaInTexture = (isTextureOk(babylonStandardMaterial.diffuseTexture) && babylonStandardMaterial.diffuseTexture.hasAlpha) ||
                                                isTextureOk(babylonStandardMaterial.opacityTexture);

                        Bitmap baseColorBitmap         = null;
                        Bitmap metallicRoughnessBitmap = null;

                        GLTFTextureInfo textureInfoBC = new GLTFTextureInfo();
                        GLTFTextureInfo textureInfoMR = new GLTFTextureInfo();

                        if (exportParameters.writeTextures)
                        {
                            // Diffuse
                            Bitmap diffuseBitmap = null;
                            if (babylonStandardMaterial.diffuseTexture != null)
                            {
                                diffuseBitmap = TextureUtilities.LoadTexture(babylonStandardMaterial.diffuseTexture.originalPath, logger);
                            }

                            // Specular
                            Bitmap specularBitmap = null;
                            if (babylonStandardMaterial.specularTexture != null)
                            {
                                if (babylonStandardMaterial.specularTexture.bitmap != null)
                                {
                                    // Specular color map has been computed by the exporter
                                    specularBitmap = babylonStandardMaterial.specularTexture.bitmap;
                                }
                                else
                                {
                                    // Specular color map is straight input
                                    specularBitmap = TextureUtilities.LoadTexture(babylonStandardMaterial.specularTexture.originalPath, logger);
                                }
                            }

                            // Opacity / Alpha / Transparency
                            Bitmap opacityBitmap = null;
                            if ((babylonStandardMaterial.diffuseTexture == null || babylonStandardMaterial.diffuseTexture.hasAlpha == false) && babylonStandardMaterial.opacityTexture != null)
                            {
                                opacityBitmap = TextureUtilities.LoadTexture(babylonStandardMaterial.opacityTexture.originalPath, logger);
                            }

                            if (diffuseBitmap != null || specularBitmap != null || opacityBitmap != null)
                            {
                                // Retreive dimensions
                                int width              = 0;
                                int height             = 0;
                                var haveSameDimensions = TextureUtilities.GetMinimalBitmapDimensions(out width, out height, diffuseBitmap, specularBitmap, opacityBitmap);
                                if (!haveSameDimensions)
                                {
                                    logger.RaiseError("Diffuse, specular and opacity maps should have same dimensions", 2);
                                }

                                // Create baseColor+alpha and metallic+roughness maps
                                baseColorBitmap         = new Bitmap(width, height);
                                metallicRoughnessBitmap = new Bitmap(width, height);
                                for (int x = 0; x < width; x++)
                                {
                                    for (int y = 0; y < height; y++)
                                    {
                                        SpecularGlossiness specularGlossinessTexture = new SpecularGlossiness
                                        {
                                            diffuse = diffuseBitmap != null ? new BabylonColor3(diffuseBitmap.GetPixel(x, y)) :
                                                      _specularGlossiness.diffuse,
                                            opacity = diffuseBitmap != null && babylonStandardMaterial.diffuseTexture.hasAlpha ? diffuseBitmap.GetPixel(x, y).A / 255.0f :
                                                      opacityBitmap != null && babylonStandardMaterial.opacityTexture.getAlphaFromRGB ? opacityBitmap.GetPixel(x, y).R / 255.0f :
                                                      opacityBitmap != null && babylonStandardMaterial.opacityTexture.getAlphaFromRGB == false?opacityBitmap.GetPixel(x, y).A / 255.0f :
                                                      _specularGlossiness.opacity,
                                            specular = specularBitmap != null ? new BabylonColor3(specularBitmap.GetPixel(x, y)) :
                                                       _specularGlossiness.specular,
                                            glossiness = babylonStandardMaterial.useGlossinessFromSpecularMapAlpha && specularBitmap != null?specularBitmap.GetPixel(x, y).A / 255.0f :
                                                         _specularGlossiness.glossiness
                                        };

                                        var displayPrints = x == width / 2 && y == height / 2;
                                        MetallicRoughness metallicRoughnessTexture = ConvertToMetallicRoughness(specularGlossinessTexture, displayPrints);

                                        Color colorBase = Color.FromArgb(
                                            (int)(metallicRoughnessTexture.opacity * 255),
                                            (int)(metallicRoughnessTexture.baseColor.r * 255),
                                            (int)(metallicRoughnessTexture.baseColor.g * 255),
                                            (int)(metallicRoughnessTexture.baseColor.b * 255)
                                            );
                                        baseColorBitmap.SetPixel(x, y, colorBase);

                                        // The metalness values are sampled from the B channel.
                                        // The roughness values are sampled from the G channel.
                                        // These values are linear. If other channels are present (R or A), they are ignored for metallic-roughness calculations.
                                        Color colorMetallicRoughness = Color.FromArgb(
                                            0,
                                            (int)(metallicRoughnessTexture.roughness * 255),
                                            (int)(metallicRoughnessTexture.metallic * 255)
                                            );
                                        metallicRoughnessBitmap.SetPixel(x, y, colorMetallicRoughness);
                                    }
                                }
                            }
                        }

                        //export textures
                        if (baseColorBitmap != null || babylonTexture.bitmap != null)
                        {
                            textureInfoBC = ExportBitmapTexture(gltf, babylonTexture, baseColorBitmap);
                            gltfPbrMetallicRoughness.baseColorTexture = textureInfoBC;
                        }

                        if (isTextureOk(babylonStandardMaterial.specularTexture))
                        {
                            textureInfoMR = ExportBitmapTexture(gltf, babylonTexture, metallicRoughnessBitmap);
                            gltfPbrMetallicRoughness.metallicRoughnessTexture = textureInfoMR;
                        }

                        //register the texture
                        AddStandText(_key, textureInfoBC, textureInfoMR);
                    }

                    // Constraints
                    if (gltfPbrMetallicRoughness.baseColorTexture != null)
                    {
                        gltfPbrMetallicRoughness.baseColorFactor = new[] { 1.0f, 1.0f, 1.0f, 1.0f };
                    }

                    if (gltfPbrMetallicRoughness.metallicRoughnessTexture != null)
                    {
                        gltfPbrMetallicRoughness.metallicFactor  = 1.0f;
                        gltfPbrMetallicRoughness.roughnessFactor = 1.0f;
                    }
                }
            }
            else if (babylonMaterial.GetType() == typeof(BabylonPBRMetallicRoughnessMaterial))
            {
                var babylonPBRMetallicRoughnessMaterial = babylonMaterial as BabylonPBRMetallicRoughnessMaterial;
                // --- prints ---
                #region prints

                logger.RaiseVerbose("GLTFExporter.Material | babylonMaterial data", 2);
                logger.RaiseVerbose("GLTFExporter.Material | babylonMaterial.alpha=" + babylonMaterial.alpha, 3);
                logger.RaiseVerbose("GLTFExporter.Material | babylonMaterial.alphaMode=" + babylonMaterial.alphaMode, 3);
                logger.RaiseVerbose("GLTFExporter.Material | babylonMaterial.backFaceCulling=" + babylonMaterial.backFaceCulling, 3);
                logger.RaiseVerbose("GLTFExporter.Material | babylonMaterial.wireframe=" + babylonMaterial.wireframe, 3);

                // Global
                logger.RaiseVerbose("GLTFExporter.Material | babylonPBRMetallicRoughnessMaterial.maxSimultaneousLights=" + babylonPBRMetallicRoughnessMaterial.maxSimultaneousLights, 3);
                logger.RaiseVerbose("GLTFExporter.Material | babylonPBRMetallicRoughnessMaterial.disableLighting=" + babylonPBRMetallicRoughnessMaterial.disableLighting, 3);
                logger.RaiseVerbose("GLTFExporter.Material | babylonPBRMetallicRoughnessMaterial.alphaCutOff=" + babylonPBRMetallicRoughnessMaterial.alphaCutOff, 3);
                logger.RaiseVerbose("GLTFExporter.Material | babylonPBRMetallicRoughnessMaterial.transparencyMode=" + babylonPBRMetallicRoughnessMaterial.transparencyMode, 3);
                logger.RaiseVerbose("GLTFExporter.Material | babylonPBRMetallicRoughnessMaterial.doubleSided=" + babylonPBRMetallicRoughnessMaterial.doubleSided, 3);

                // Base color
                logger.RaiseVerbose("GLTFExporter.Material | babylonPBRMetallicRoughnessMaterial.baseColor.Length=" + babylonPBRMetallicRoughnessMaterial.baseColor.Length, 3);
                for (int i = 0; i < babylonPBRMetallicRoughnessMaterial.baseColor.Length; i++)
                {
                    logger.RaiseVerbose("GLTFExporter.Material | babylonPBRMetallicRoughnessMaterial.baseColor[" + i + "]=" + babylonPBRMetallicRoughnessMaterial.baseColor[i], 3);
                }
                if (babylonPBRMetallicRoughnessMaterial.baseTexture == null)
                {
                    logger.RaiseVerbose("GLTFExporter.Material | babylonPBRMetallicRoughnessMaterial.baseTexture=null", 3);
                }

                // Metallic+roughness
                logger.RaiseVerbose("GLTFExporter.Material | babylonPBRMetallicRoughnessMaterial.metallic=" + babylonPBRMetallicRoughnessMaterial.metallic, 3);
                logger.RaiseVerbose("GLTFExporter.Material | babylonPBRMetallicRoughnessMaterial.roughness=" + babylonPBRMetallicRoughnessMaterial.roughness, 3);
                if (babylonPBRMetallicRoughnessMaterial.metallicRoughnessTexture == null)
                {
                    logger.RaiseVerbose("GLTFExporter.Material | babylonPBRMetallicRoughnessMaterial.metallicRoughnessTexture=null", 3);
                }

                // Normal / bump
                if (babylonPBRMetallicRoughnessMaterial.normalTexture == null)
                {
                    logger.RaiseVerbose("GLTFExporter.Material | babylonPBRMetallicRoughnessMaterial.normalTexture=null", 3);
                }
                logger.RaiseVerbose("GLTFExporter.Material | babylonPBRMetallicRoughnessMaterial.invertNormalMapX=" + babylonPBRMetallicRoughnessMaterial.invertNormalMapX, 3);
                logger.RaiseVerbose("GLTFExporter.Material | babylonPBRMetallicRoughnessMaterial.invertNormalMapY=" + babylonPBRMetallicRoughnessMaterial.invertNormalMapY, 3);

                // Emissive
                for (int i = 0; i < babylonPBRMetallicRoughnessMaterial.emissive.Length; i++)
                {
                    logger.RaiseVerbose("GLTFExporter.Material | babylonPBRMetallicRoughnessMaterial.emissiveColor[" + i + "]=" + babylonPBRMetallicRoughnessMaterial.emissive[i], 3);
                }
                if (babylonPBRMetallicRoughnessMaterial.emissiveTexture == null)
                {
                    logger.RaiseVerbose("GLTFExporter.Material | babylonPBRMetallicRoughnessMaterial.emissiveTexture=null", 3);
                }

                // Ambient occlusion
                logger.RaiseVerbose("GLTFExporter.Material | babylonPBRMetallicRoughnessMaterial.occlusionStrength=" + babylonPBRMetallicRoughnessMaterial.occlusionStrength, 3);
                if (babylonPBRMetallicRoughnessMaterial.occlusionTexture == null)
                {
                    logger.RaiseVerbose("GLTFExporter.Material | babylonPBRMetallicRoughnessMaterial.occlusionTexture=null", 3);
                }
                #endregion


                // --------------------------------
                // --------- gltfMaterial ---------
                // --------------------------------

                logger.RaiseMessage("GLTFExporter.Material | create gltfMaterial", 2);
                gltfMaterial = new GLTFMaterial
                {
                    name = name
                };
                gltfMaterial.id    = babylonMaterial.id;
                gltfMaterial.index = gltf.MaterialsList.Count;
                gltf.MaterialsList.Add(gltfMaterial);

                // Alpha
                string alphaMode;
                float? alphaCutoff;
                getAlphaMode(babylonPBRMetallicRoughnessMaterial, out alphaMode, out alphaCutoff);
                gltfMaterial.alphaMode   = alphaMode;
                gltfMaterial.alphaCutoff = alphaCutoff;

                // DoubleSided
                gltfMaterial.doubleSided = babylonPBRMetallicRoughnessMaterial.doubleSided;

                // Normal
                gltfMaterial.normalTexture = ExportTexture(babylonPBRMetallicRoughnessMaterial.normalTexture, gltf);

                // Occlusion
                if (babylonPBRMetallicRoughnessMaterial.occlusionTexture != null)
                {
                    if (babylonPBRMetallicRoughnessMaterial.occlusionTexture.bitmap != null)
                    {
                        // ORM texture has been merged manually by the exporter
                        // Occlusion is defined as well as metallic and/or roughness
                        logger.RaiseVerbose("Occlusion is defined as well as metallic and/or roughness", 2);
                        gltfMaterial.occlusionTexture = ExportBitmapTexture(gltf, babylonPBRMetallicRoughnessMaterial.occlusionTexture);
                    }
                    else
                    {
                        // ORM texture was already merged or only occlusion is defined
                        logger.RaiseVerbose("ORM texture was already merged or only occlusion is defined", 2);
                        gltfMaterial.occlusionTexture = ExportTexture(babylonPBRMetallicRoughnessMaterial.occlusionTexture, gltf);
                    }
                }

                // Emissive
                gltfMaterial.emissiveFactor  = babylonPBRMetallicRoughnessMaterial.emissive;
                gltfMaterial.emissiveTexture = ExportTexture(babylonPBRMetallicRoughnessMaterial.emissiveTexture, gltf);


                // --------------------------------
                // --- gltfPbrMetallicRoughness ---
                // --------------------------------

                logger.RaiseMessage("GLTFExporter.Material | create gltfPbrMetallicRoughness", 2);
                var gltfPbrMetallicRoughness = new GLTFPBRMetallicRoughness();
                gltfMaterial.pbrMetallicRoughness = gltfPbrMetallicRoughness;

                // --- Global ---

                // Base color
                gltfPbrMetallicRoughness.baseColorFactor = new float[4]
                {
                    babylonPBRMetallicRoughnessMaterial.baseColor[0],
                    babylonPBRMetallicRoughnessMaterial.baseColor[1],
                    babylonPBRMetallicRoughnessMaterial.baseColor[2],
                    babylonPBRMetallicRoughnessMaterial.alpha
                };
                if (babylonPBRMetallicRoughnessMaterial.baseTexture != null)
                {
                    if (babylonPBRMetallicRoughnessMaterial.baseTexture.bitmap != null)
                    {
                        gltfPbrMetallicRoughness.baseColorTexture = ExportBitmapTexture(gltf, babylonPBRMetallicRoughnessMaterial.baseTexture);
                    }
                    else
                    {
                        gltfPbrMetallicRoughness.baseColorTexture = ExportTexture(babylonPBRMetallicRoughnessMaterial.baseTexture, gltf);
                    }
                }

                // Metallic roughness
                gltfPbrMetallicRoughness.metallicFactor  = babylonPBRMetallicRoughnessMaterial.metallic;
                gltfPbrMetallicRoughness.roughnessFactor = babylonPBRMetallicRoughnessMaterial.roughness;
                if (babylonPBRMetallicRoughnessMaterial.metallicRoughnessTexture != null)
                {
                    if (babylonPBRMetallicRoughnessMaterial.metallicRoughnessTexture == babylonPBRMetallicRoughnessMaterial.occlusionTexture)
                    {
                        // Occlusion is defined as well as metallic and/or roughness
                        // Use same texture
                        logger.RaiseVerbose("Occlusion is defined as well as metallic and/or roughness", 2);
                        gltfPbrMetallicRoughness.metallicRoughnessTexture = gltfMaterial.occlusionTexture;
                    }
                    else
                    {
                        // Occlusion is not defined, only metallic and/or roughness
                        logger.RaiseVerbose("Occlusion is not defined, only metallic and/or roughness", 2);

                        if (babylonPBRMetallicRoughnessMaterial.metallicRoughnessTexture.bitmap != null)
                        {
                            // Metallic & roughness texture has been merged manually by the exporter
                            // Write bitmap file
                            logger.RaiseVerbose("Metallic & roughness texture has been merged manually by the exporter", 2);
                            gltfPbrMetallicRoughness.metallicRoughnessTexture = ExportBitmapTexture(gltf, babylonPBRMetallicRoughnessMaterial.metallicRoughnessTexture);
                        }
                        else
                        {
                            // Metallic & roughness texture was already merged
                            // Copy file
                            logger.RaiseVerbose("Metallic & roughness texture was already merged", 2);
                            gltfPbrMetallicRoughness.metallicRoughnessTexture = ExportTexture(babylonPBRMetallicRoughnessMaterial.metallicRoughnessTexture, gltf);
                        }
                    }
                }
            }
            else
            {
                logger.RaiseWarning("GLTFExporter.Material | Unsupported material type: " + babylonMaterial.GetType(), 2);
            }

            if (gltfMaterial != null && babylonMaterial.isUnlit)
            {
                // Add Unlit extension
                if (!exportParameters.enableKHRMaterialsUnlit)
                {
                    logger.RaiseWarning("GLTFExporter.Material | KHR_materials_unlit has not been enabled for export!", 2);
                }
                else
                {
                    if (gltfMaterial.extensions == null)
                    {
                        gltfMaterial.extensions = new GLTFExtensions();
                    }
                    if (gltf.extensionsUsed == null)
                    {
                        gltf.extensionsUsed = new System.Collections.Generic.List <string>();
                    }
                    if (!gltf.extensionsUsed.Contains("KHR_materials_unlit"))
                    {
                        gltf.extensionsUsed.Add("KHR_materials_unlit");
                    }
                    gltfMaterial.extensions["KHR_materials_unlit"] = new object();
                }
            }

            ExportGLTFExtension(babylonMaterial, ref gltfMaterial, gltf);
        }
 private void CopyGltfTexture(string sourcePath, string destPath)
 {
     TextureUtilities.CopyTexture(sourcePath, destPath, exportParameters.txtQuality, logger);
 }
Пример #30
0
        public void Save(Stream destination, ObjectDatabase objectDatabase, TextureDatabase textureDatabase, BoneDatabase boneDatabase, bool leaveOpen = false)
        {
            if (objectDatabase != null)
            {
                foreach (var mesh in Meshes)
                {
                    mesh.ID = objectDatabase.GetMesh(mesh.Name)?.ID ?? mesh.ID;
                }
            }

            if (boneDatabase != null)
            {
                string fileName = (destination is FileStream fileStream) ? Path.GetFileName(fileStream.Name) : string.Empty;

                // Assume we are exporting in game's style
                var skeleton = boneDatabase.Skeletons.FirstOrDefault(x => fileName.StartsWith(x.Name, StringComparison.OrdinalIgnoreCase));

                // If we couldn't find it, default to CMN skeleton
                if (skeleton == null)
                {
                    skeleton = boneDatabase.Skeletons.FirstOrDefault(x => x.Name.Equals("CMN", StringComparison.OrdinalIgnoreCase));
                }

                // Still?? Then default to the first skeleton (this is unlikely to happen though)
                if (skeleton == null)
                {
                    skeleton = boneDatabase.Skeletons[0];
                }

                // Pretty much impossible to miss
                if (skeleton != null)
                {
                    foreach (var skin in Meshes.Where(x => x.Skin != null).Select(x => x.Skin))
                    {
                        foreach (var bone in skin.Bones)
                        {
                            int index = skin.ExData?.BoneNames?.FindIndex(x => x.Equals(bone.Name, StringComparison.OrdinalIgnoreCase)) ?? -1;
                            if (index == -1)
                            {
                                index = skeleton.BoneNames1.FindIndex(x => x.Equals(bone.Name, StringComparison.OrdinalIgnoreCase));
                            }
                            else
                            {
                                index = 0x8000 | index;
                            }

                            if (index != -1)
                            {
                                // Before we do this, fix the child bones
                                foreach (var childBone in skin.Bones.Where(x => x.ParentID.Equals(bone.ID)))
                                {
                                    childBone.ParentID = index;
                                }

                                // Now replace the ID
                                bone.ID = index;
                            }
                            else
                            {
                                Debug.WriteLine($"Model.Save: Bone wasn't found in bone database or ex-data: {bone.Name}");
                            }
                        }
                    }
                }
            }

            if (textureDatabase != null && TextureSet != null)
            {
                var newIDs    = new List <int>(TextureSet.Textures.Count);
                int currentID = textureDatabase.Textures.Max(x => x.ID) + 1;
                foreach (var texture in TextureSet.Textures)
                {
                    var textureEntry = !string.IsNullOrEmpty(texture.Name) ?
                                       textureDatabase.GetTexture(texture.Name) : textureDatabase.GetTexture(texture.ID);

                    if (textureEntry == null)
                    {
                        textureDatabase.Textures.Add(textureEntry = new TextureEntry
                        {
                            ID   = currentID++,
                            Name = texture.Name ?? $"Texture{currentID}",
                        });
                    }

                    newIDs.Add(textureEntry.ID);
                }

                if (!newIDs.SequenceEqual(TextureIDs))
                {
                    TextureUtilities.ReAssignTextureIDs(this, newIDs);
                }
            }

            Save(destination, leaveOpen);
        }