예제 #1
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);
        }
예제 #2
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);
        }