Example #1
0
        public void GenerateBabylonFile(string file, string outputFile, bool skinned, bool rightToLeft)
        {
            if (OnImportProgressChanged != null)
                OnImportProgressChanged(0);


            var scene = new BabylonScene(Path.GetDirectoryName(outputFile));

            var services = new ServiceContainer();

            // Create a graphics device
            var form = new Form();
            
            services.AddService<IGraphicsDeviceService>(GraphicsDeviceService.AddRef(form.Handle, 1, 1));

            var contentBuilder = new ContentBuilder(ExtraPipelineAssemblies);
            var contentManager = new ContentManager(services, contentBuilder.OutputDirectory);

            // Tell the ContentBuilder what to build.
            contentBuilder.Clear();
            contentBuilder.Add(Path.GetFullPath(file), "Model", Importer, skinned ? "SkinnedModelProcessor" : "ModelProcessor");

            // Build this new model data.
            string buildError = contentBuilder.Build();

            if (string.IsNullOrEmpty(buildError))
            {
                var model = contentManager.Load<Model>("Model");
                ParseModel(model, scene, rightToLeft);
            }
            else
            {
                throw new Exception(buildError);
            }

            // Output
            scene.Prepare();
            using (var outputStream = new FileStream(outputFile, FileMode.Create, FileAccess.Write))
            {
                var ser = new DataContractJsonSerializer(typeof(BabylonScene));
                ser.WriteObject(outputStream, scene);
            }

            // Cleaning
            foreach (var path in exportedTexturesFilename.Values)
            {
                File.Delete(path);
            }

            if (OnImportProgressChanged != null)
                OnImportProgressChanged(100);
        }
        void Generate(NovaScene scene, string outputFile)
        {
            ReportProgressChanged(25);
            var babylonScene = new BabylonScene(Path.GetDirectoryName(outputFile));
            alreadyExportedTextures.Clear();

            babylonScene.autoClear = scene.AutoClear;
            babylonScene.clearColor = scene.ClearColor.ToArray();
            babylonScene.ambientColor = scene.AmbientColor.ToArray();
            babylonScene.gravity = ((scene.Gravity == Vector3.Zero) ? new Vector3(0, -9.0f, 0) : scene.Gravity).ToArray();

            // Fog
            babylonScene.fogMode = (int)scene.FogMode;
            babylonScene.fogColor = scene.FogColor.ToArray();
            babylonScene.fogStart = scene.ActiveCamera.NearClip;
            babylonScene.fogEnd = scene.ActiveCamera.FarClip;
            babylonScene.fogDensity = scene.FogDensity;

            // Cameras
            DumpCameras(scene, babylonScene);

            // Lights
            DumpLights(scene, babylonScene);
            ReportProgressChanged(50);

            // Objects
            DumpObjects(scene, babylonScene);

            // Materials
            DumpMaterials(babylonScene);

            // Particles
            DumpParticles(babylonScene);

            // Lens flares
            DumpLensFlares(babylonScene);

            // Output
            babylonScene.Prepare(false);
            using (var outputStream = new FileStream(outputFile, FileMode.Create, FileAccess.Write))
            {
                var ser = new DataContractJsonSerializer(typeof(BabylonScene));
                ser.WriteObject(outputStream, babylonScene);
            }
            ReportProgressChanged(100);
        }
Example #3
0
        void ParseModel(Model model, BabylonScene scene, bool rightToLeft)
        {
            var effects = model.Meshes.SelectMany(m => m.Effects).ToList();
            var meshes = model.Meshes.ToList();
            var total = effects.Count + meshes.Count;
            var progress = 0;
            SkinningData skinningData = null;
            BabylonSkeleton currentSkeleton = null;

            if (model.Tag != null)
            {
                skinningData = model.Tag as SkinningData;
            }

            if (skinningData != null)
            {
                var skeleton = new BabylonSkeleton();
                skeleton.id = scene.SkeletonsList.Count;
                skeleton.name = "Skeleton" + scene.SkeletonsList.Count;
                ParseBones(skinningData, skeleton);

                // Animations
                ParseAnimationClip(skinningData, skeleton);

                scene.SkeletonsList.Add(skeleton);
                currentSkeleton = skeleton;
            }

            foreach (Effect effect in effects)
            {
                ParseEffect(effect, scene);
                if (OnImportProgressChanged != null)
                    OnImportProgressChanged(((progress++) * 100) / total);
            }

            foreach (var mesh in meshes)
            {
                ParseMesh(mesh, scene, currentSkeleton, rightToLeft);
                if (OnImportProgressChanged != null)
                    OnImportProgressChanged(((progress++) * 100) / total);
            }
        }
Example #4
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="baseColorTexMap"></param>
        /// <param name="alphaTexMap">Transparency weight map</param>
        /// <param name="baseColor"></param>
        /// <param name="alpha"></param>
        /// <param name="babylonScene"></param>
        /// <param name="materialName"></param>
        /// <returns></returns>
        private BabylonTexture ExportBaseColorAlphaTexture(ITexmap baseColorTexMap, ITexmap alphaTexMap, float[] baseColor, float alpha, BabylonScene babylonScene, string materialName)
        {
            // --- Babylon texture ---

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

            if (alphaTexture == null && baseColorTexture != null && alpha == 1)
            {
                if (baseColorTexture.AlphaSource == 0 &&
                    (baseColorTexture.Map.FullFilePath.EndsWith(".tif") || baseColorTexture.Map.FullFilePath.EndsWith(".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);
                }

                var extension = Path.GetExtension(baseColorTexture.Map.FullFilePath).ToLower();
                if (baseColorTexture.AlphaSource == 3 && // 'None (Opaque)'
                    extension == ".jpg" || extension == ".jpeg" || extension == ".bmp")
                {
                    // Copy base color image
                    return(ExportTexture(baseColorTexture, babylonScene));
                }
            }

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

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

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

            string nameText = null;

            nameText = (baseColorTexture != null ? Path.GetFileNameWithoutExtension(baseColorTexture.Map.FullFilePath) : ColorToStringName(baseColor)) +
                       (alphaTexture != null ? Path.GetFileNameWithoutExtension(alphaTexture.Map.FullFilePath) : ("" + (int)(alpha * 255))) +
                       (alphaTexture == null && baseColorTexture == null ? materialName : "") + "_baseColor";

            var babylonTexture = new BabylonTexture
            {
                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
            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)) &&
                (baseColorTexture.Map.FullFilePath.EndsWith(".tif") || baseColorTexture.Map.FullFilePath.EndsWith(".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 = _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
                            var alphaColor   = alphaBitmap.GetPixel(x, y);
                            var alphaAtPixel = 255 - (getAlphaFromRGB ? alphaColor.R : alphaColor.A);
                            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);
                    SaveBitmap(baseColorAlphaBitmap, babylonScene.OutputPath, babylonTexture.name, imageFormat);
                }
                else
                {
                    // Store created bitmap for further use in gltf export
                    babylonTexture.bitmap = baseColorAlphaBitmap;
                }
            }

            return(babylonTexture);
        }
Example #5
0
        private BabylonTexture ExportBaseColorAlphaTexture(MFnDependencyNode baseColorTextureDependencyNode, MFnDependencyNode opacityTextureDependencyNode, BabylonScene babylonScene, string materialName, Color defaultBaseColor, float defaultOpacity = 1.0f)
        {
            // Prints
            if (baseColorTextureDependencyNode != null)
            {
                Print(baseColorTextureDependencyNode, logRankTexture, "Print ExportBaseColorAlphaTexture baseColorTextureDependencyNode");
            }
            if (opacityTextureDependencyNode != null)
            {
                Print(opacityTextureDependencyNode, logRankTexture, "Print ExportBaseColorAlphaTexture opacityTextureDependencyNode");
            }

            // Use one as a reference for UVs parameters
            var textureDependencyNode = baseColorTextureDependencyNode != null ? baseColorTextureDependencyNode : opacityTextureDependencyNode;

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

            var id             = textureDependencyNode.uuid().asString();
            var babylonTexture = new BabylonTexture(id)
            {
                name = materialName + "_baseColor" + ".png" // TODO - unsafe name, may conflict with another texture name
            };

            // Level
            babylonTexture.level = 1.0f;

            // Alpha
            babylonTexture.hasAlpha        = opacityTextureDependencyNode != null || defaultOpacity != 1.0f;
            babylonTexture.getAlphaFromRGB = false;

            // UVs
            _exportUV(textureDependencyNode, babylonTexture);

            // Is cube
            string sourcePath = getSourcePathFromFileTexture(textureDependencyNode);

            if (sourcePath == null)
            {
                return(null);
            }
            if (sourcePath == "")
            {
                RaiseError("Texture path is missing.", logRankTexture + 1);
                return(null);
            }
            _exportIsCube(sourcePath, babylonTexture, false);


            // --- Merge base color and opacity maps ---

            if (CopyTexturesToOutput)
            {
                // Load bitmaps
                var baseColorBitmap = LoadTexture(baseColorTextureDependencyNode);
                var opacityBitmap   = LoadTexture(opacityTextureDependencyNode);

                // Merge bitmaps
                Bitmap[] bitmaps              = new Bitmap[] { baseColorBitmap, baseColorBitmap, baseColorBitmap, opacityBitmap };
                int[]    defaultValues        = new int[] { defaultBaseColor.R, defaultBaseColor.G, defaultBaseColor.B, (int)(defaultOpacity * 255) };
                Bitmap   baseColorAlphaBitmap = MergeBitmaps(bitmaps, defaultValues, "Base color and opacity");

                // Write bitmap
                if (isBabylonExported)
                {
                    RaiseMessage($"Texture | write image '{babylonTexture.name}'", logRankTexture + 1);
                    SaveBitmap(baseColorAlphaBitmap, babylonScene.OutputPath, babylonTexture.name, System.Drawing.Imaging.ImageFormat.Png);
                }
                else
                {
                    // Store created bitmap for further use in gltf export
                    babylonTexture.bitmap = baseColorAlphaBitmap;
                }
            }

            return(babylonTexture);
        }
Example #6
0
        void ParseMesh(ModelMesh modelMesh, BabylonScene scene, BabylonSkeleton skeleton, bool rightToLeft)
        {
            var proxyID = ProxyMesh.CreateBabylonMesh(modelMesh.Name, scene);
            int indexName = 0;

            foreach (var part in modelMesh.MeshParts)
            {
                var material = exportedMaterials.First(m => m.Name == part.Effect.GetHashCode().ToString());

                var indices = new ushort[part.PrimitiveCount * 3];
                part.IndexBuffer.GetData(part.StartIndex * 2, indices, 0, indices.Length);

                if (rightToLeft)
                {
                    for (int ib = 0; ib < indices.Length; ib += 3) // reverse winding of triangles
                    {
                        ushort ti = indices[ib];
                        indices[ib] = indices[ib + 2];
                        indices[ib + 2] = ti;
                    }
                }

                if (part.VertexBuffer.VertexDeclaration.VertexStride >= PositionNormalTexturedWeights.Stride)
                {
                    var mesh = new Mesh<PositionNormalTexturedWeights>(material);
                    var vertices = new PositionNormalTexturedWeights[part.NumVertices];

                    part.VertexBuffer.GetData(part.VertexOffset * part.VertexBuffer.VertexDeclaration.VertexStride, vertices, 0, vertices.Length, part.VertexBuffer.VertexDeclaration.VertexStride);

                    for (int index = 0; index < vertices.Length; index++)
                    {
                        vertices[index].TextureCoordinates.Y = 1.0f - vertices[index].TextureCoordinates.Y;
                        if (rightToLeft)
                        {
                            vertices[index].Position.Z = -vertices[index].Position.Z;
                            vertices[index].Normal.Z = -vertices[index].Normal.Z;
                        }
                    }

                    mesh.AddPart(modelMesh.Name+"#"+indexName.ToString(), vertices.ToList(), indices.Select(i => (int)i).ToList());
                    mesh.CreateBabylonMesh(scene, proxyID, skeleton);
                }
                else
                {
                    if (part.VertexBuffer.VertexDeclaration.VertexStride < PositionNormalTextured.Stride) return; // Error: Not a PositionNormalTextured mesh!
                    var mesh = new Mesh<PositionNormalTextured>(material);
                    var vertices = new PositionNormalTextured[part.NumVertices];
                    part.VertexBuffer.GetData(part.VertexOffset * part.VertexBuffer.VertexDeclaration.VertexStride, vertices, 0, vertices.Length, part.VertexBuffer.VertexDeclaration.VertexStride);

                    for (int index = 0; index < vertices.Length; index++)
                    {
                        vertices[index].TextureCoordinates.Y = 1.0f - vertices[index].TextureCoordinates.Y;
                        if (rightToLeft)
                        {
                            vertices[index].Position.Z = -vertices[index].Position.Z;
                            vertices[index].Normal.Z = -vertices[index].Normal.Z;
                        }
                    }

                    mesh.AddPart(modelMesh.Name + "#" + indexName.ToString(), vertices.ToList(), indices.Select(i => (int)i).ToList());
                    mesh.CreateBabylonMesh(scene, proxyID, skeleton);
                }

                indexName++;
            }
        }
Example #7
0
 public BabylonTexture ExportTexture(MFnDependencyNode materialDependencyNode, string plugName, BabylonScene babylonScene, bool allowCube = false, bool forceAlpha = false, bool updateCoordinatesMode = false, float amount = 1.0f)
 {
     logRankTexture = 2;
     return(_ExportTexture(materialDependencyNode, plugName, babylonScene, allowCube, forceAlpha, updateCoordinatesMode, amount));
 }
Example #8
0
        /*
         * private BabylonTexture ExportBaseColorAlphaTexture(MFnDependencyNode materialDependencyNode, bool useColorMap, bool useOpacityMap, float[] baseColor, float alpha, BabylonScene babylonScene)
         * {
         *  MFnDependencyNode textureDependencyNode = getTextureDependencyNode(materialDependencyNode, "TEX_color_map");
         *
         *  if (textureDependencyNode == null)
         *  {
         *      return null;
         *  }
         *
         *  // Prints
         *  Print(textureDependencyNode, logRankTexture, "Print ExportBaseColorAlphaTexture textureDependencyNode");
         *
         *  // Retreive texture file path
         *  string sourcePath = getSourcePathFromFileTexture(textureDependencyNode);
         *  if (sourcePath == null)
         *  {
         *      return null;
         *  }
         *  if (sourcePath == "")
         *  {
         *      RaiseError("Texture path is missing.", logRankTexture + 1);
         *      return null;
         *  }
         *
         *  // Check format
         *  string extension = Path.GetExtension(sourcePath);
         *  var validImageFormat = 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)), logRankTexture + 1);
         *      return null;
         *  }
         *  RaiseVerbose("validImageFormat=" + validImageFormat, logRankTexture + 1);
         *
         *  extension = extension.Substring(1).ToLower(); // remove the dot
         *  if (useOpacityMap)
         *  {
         *      List<string> alphaFormats = new List<string>(new string[] { "png", "tga", "gif" });
         *      if (!alphaFormats.Contains(extension))
         *      {
         *          validImageFormat = "png";
         *      }
         *  }
         *  else
         *  {
         *      List<string> nonAlphaFormats = new List<string>(new string[] { "jpg", "jpeg", "bmp" });
         *      if (!nonAlphaFormats.Contains(extension))
         *      {
         *          validImageFormat = "jpg";
         *      }
         *  }
         *
         *  var babylonTexture = new BabylonTexture
         *  {
         *      name = Path.GetFileNameWithoutExtension(sourcePath) + "." + validImageFormat
         *  };
         *
         *  // Level
         *  babylonTexture.level = 1.0f;
         *
         *  // UVs
         *  _exportUV(textureDependencyNode, babylonTexture);
         *
         *  // Is cube
         *  _exportIsCube(sourcePath, babylonTexture, false);
         *
         *
         *  // --- Merge baseColor and alpha maps ---
         *
         *  if (!File.Exists(sourcePath))
         *  {
         *      return null;
         *  }
         *
         *  // Alpha
         *  babylonTexture.hasAlpha = useOpacityMap;
         *  babylonTexture.getAlphaFromRGB = false;
         *
         *  if (CopyTexturesToOutput)
         *  {
         *      // Load bitmaps
         *      var baseColorBitmap = LoadTexture(sourcePath);
         *
         *      // Retreive dimensions
         *      int width = baseColorBitmap.Width;
         *      int height = baseColorBitmap.Height;
         *
         *      // 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.GetPixel(x, y);
         *
         *              var __baseColor = useColorMap ? baseColorAtPixel : _baseColor;
         *              var __alpha = useOpacityMap ? baseColorAtPixel.A : _alpha;
         *              Color baseColorAlpha = Color.FromArgb(__alpha, __baseColor);
         *              baseColorAlphaBitmap.SetPixel(x, y, baseColorAlpha);
         *          }
         *      }
         *
         *      // Write bitmap
         *      if (isBabylonExported)
         *      {
         *          RaiseMessage($"Texture | write image '{babylonTexture.name}'", logRankTexture + 1);
         *          var imageFormat = useOpacityMap ? System.Drawing.Imaging.ImageFormat.Png : System.Drawing.Imaging.ImageFormat.Jpeg;
         *          SaveBitmap(baseColorAlphaBitmap, babylonScene.OutputPath, babylonTexture.name, imageFormat);
         *      }
         *      else
         *      {
         *          // Store created bitmap for further use in gltf export
         *          babylonTexture.bitmap = baseColorAlphaBitmap;
         *      }
         *  }
         *
         *  return babylonTexture;
         * }
         */

        private BabylonTexture ExportORMTexture(BabylonScene babylonScene, MFnDependencyNode metallicTextureDependencyNode, MFnDependencyNode roughnessTextureDependencyNode, MFnDependencyNode ambientOcclusionTextureDependencyNode, float defaultMetallic, float defaultRoughness)
        {
            // Prints
            if (metallicTextureDependencyNode != null)
            {
                Print(metallicTextureDependencyNode, logRankTexture, "Print ExportORMTexture metallicTextureDependencyNode");
            }
            if (roughnessTextureDependencyNode != null)
            {
                Print(roughnessTextureDependencyNode, logRankTexture, "Print ExportORMTexture roughnessTextureDependencyNode");
            }
            if (ambientOcclusionTextureDependencyNode != null)
            {
                Print(ambientOcclusionTextureDependencyNode, logRankTexture, "Print ExportORMTexture ambientOcclusionTextureDependencyNode");
            }

            // Use metallic or roughness texture as a reference for UVs parameters
            var textureDependencyNode = metallicTextureDependencyNode != null ? metallicTextureDependencyNode : roughnessTextureDependencyNode;

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

            var id = textureDependencyNode.uuid().asString();

            var babylonTexture = new BabylonTexture(id)
            {
                name = (ambientOcclusionTextureDependencyNode != null ? ambientOcclusionTextureDependencyNode.name : "") +
                       (roughnessTextureDependencyNode != null ? roughnessTextureDependencyNode.name : ("" + (int)(defaultRoughness * 255))) +
                       (metallicTextureDependencyNode != null ? metallicTextureDependencyNode.name : ("" + (int)(defaultMetallic * 255))) + ".jpg" // TODO - unsafe name, may conflict with another texture name
            };

            // UVs
            _exportUV(textureDependencyNode, babylonTexture);

            // Is cube
            string sourcePath = getSourcePathFromFileTexture(textureDependencyNode);

            if (sourcePath == null)
            {
                return(null);
            }
            if (sourcePath == "")
            {
                RaiseError("Texture path is missing.", logRankTexture + 1);
                return(null);
            }
            _exportIsCube(sourcePath, babylonTexture, false);


            // --- Merge metallic, roughness, ambient occlusion maps ---
            if (CopyTexturesToOutput)
            {
                // Load bitmaps
                var metallicBitmap         = LoadTexture(metallicTextureDependencyNode);
                var roughnessBitmap        = LoadTexture(roughnessTextureDependencyNode);
                var ambientOcclusionBitmap = LoadTexture(ambientOcclusionTextureDependencyNode);

                // Merge bitmaps
                // 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.
                Bitmap[] bitmaps       = new Bitmap[] { ambientOcclusionBitmap, roughnessBitmap, metallicBitmap, null };
                int[]    defaultValues = new int[] { 0, (int)(defaultRoughness * 255), (int)(defaultMetallic * 255), 0 };
                Bitmap   ormBitmap     = MergeBitmaps(bitmaps, defaultValues, ambientOcclusionBitmap != null ? "Occlusion, metallic and roughness" : "Metallic and roughness");

                // Write bitmap
                if (isBabylonExported)
                {
                    RaiseMessage($"Texture | write image '{babylonTexture.name}'", logRankTexture + 1);
                    SaveBitmap(ormBitmap, babylonScene.OutputPath, babylonTexture.name, System.Drawing.Imaging.ImageFormat.Jpeg);
                }
                else
                {
                    // Store created bitmap for further use in gltf export
                    babylonTexture.bitmap = ormBitmap;
                }
            }

            return(babylonTexture);
        }
Example #9
0
        private BabylonTexture ExportPBRTexture(IIGameMaterial materialNode, int index, BabylonScene babylonScene, float amount = 1.0f, bool allowCube = false)
        {
            var texMap = _getTexMap(materialNode, index);

            if (texMap != null)
            {
                return(ExportTexture(texMap, babylonScene, amount, allowCube));
            }
            return(null);
        }
        private BabylonShadowGenerator ExportShadowGenerator(IINode lightNode, BabylonScene babylonScene)
        {
            var maxLight = (lightNode.ObjectRef as ILightObject);
            var babylonShadowGenerator = new BabylonShadowGenerator();

            RaiseMessage("Exporting shadow map", 2);

            babylonShadowGenerator.lightId = lightNode.GetGuid().ToString();

            babylonShadowGenerator.mapSize = maxLight.GetMapSize(0, Tools.Forever);

            babylonShadowGenerator.bias = lightNode.GetFloatProperty("babylonjs_shadows_bias", 0.00005f);
            babylonShadowGenerator.forceBackFacesOnly = lightNode.GetBoolProperty("babylonjs_forcebackfaces");

            var shadowsType = lightNode.GetStringProperty("babylonjs_shadows_type", "Blurred Variance");

            switch (shadowsType)
            {
            case "Hard shadows":
                break;

            case "Poisson Sampling":
                babylonShadowGenerator.usePoissonSampling = true;
                break;

            case "Variance":
                babylonShadowGenerator.useVarianceShadowMap = true;
                break;

            case "Blurred Variance":
                babylonShadowGenerator.useBlurVarianceShadowMap = true;
                babylonShadowGenerator.blurScale     = lightNode.GetFloatProperty("babylonjs_shadows_blurScale", 2);
                babylonShadowGenerator.blurBoxOffset = lightNode.GetFloatProperty("babylonjs_shadows_blurBoxOffset", 1);
                break;
            }


            var list = new List <string>();

            var inclusion          = maxLight.ExclList.TestFlag(1); //NT_INCLUDE
            var checkExclusionList = maxLight.ExclList.TestFlag(4); //NT_AFFECT_SHADOWCAST

            foreach (var meshNode in Loader.Core.RootNode.NodesListBySuperClass(SClass_ID.Geomobject))
            {
#if MAX2017
                if (meshNode.CastShadows)
#else
                if (meshNode.CastShadows == 1)
#endif
                {
                    var inList = maxLight.ExclList.FindNode(meshNode) != -1;

                    if (!checkExclusionList || (inList && inclusion) || (!inList && !inclusion))
                    {
                        list.Add(meshNode.GetGuid().ToString());
                    }
                }
            }
            babylonShadowGenerator.renderList = list.ToArray();

            babylonScene.ShadowGeneratorsList.Add(babylonShadowGenerator);
            return(babylonShadowGenerator);
        }
Example #11
0
        private void ExportSkin(IIGameSkin skin, BabylonScene babylonScene)
        {
            var babylonSkeleton = new BabylonSkeleton {
                id = skins.IndexOf(skin)
            };

            babylonSkeleton.name = "skeleton #" + babylonSkeleton.id;

            RaiseMessage(babylonSkeleton.name, 1);

            var skinIndex      = skins.IndexOf(skin);
            var meshNode       = skinnedNodes[skinIndex];
            var skinInitMatrix = meshNode.GetObjectTM(0);

            var bones         = new List <BabylonBone>();
            var gameBones     = new List <IIGameNode>();
            var boneIds       = new List <int>();
            var bindPoseInfos = new List <BonePoseInfo>();

            for (int i = 0; i < skin.TotalSkinBoneCount; ++i)
            {
                bones.Add(null);
                gameBones.Add(null);
                boneIds.Add(-1);
                bindPoseInfos.Add(null);
            }
            for (var index = 0; index < skin.TotalSkinBoneCount; index++)
            {
                var gameBone = skin.GetIGameBone(index, false);

                var sortedIndex = skinSortedBones[skin].IndexOf(gameBone.NodeID);

                gameBones[sortedIndex] = (gameBone);
                boneIds[sortedIndex]   = (gameBone.NodeID);
                bones[sortedIndex]     = (new BabylonBone {
                    index = sortedIndex, name = gameBone.Name
                });

                var boneInitMatrix = gameBone.GetObjectTM(0);
                bindPoseInfos[sortedIndex] = (new BonePoseInfo {
                    AbsoluteTransform = boneInitMatrix
                });
            }

            // fix hierarchy an generate animation keys
            var exportNonOptimizedAnimations = Loader.Core.RootNode.GetBoolProperty("babylonjs_exportnonoptimizedanimations");

            for (var index = 0; index < skin.TotalSkinBoneCount; index++)
            {
                var gameBone = gameBones[index];
                var parent   = gameBone.NodeParent;
                var babBone  = bones[index];
                if (parent != null)
                {
                    babBone.parentBoneIndex = boneIds.IndexOf(parent.NodeID);
                }
                if (babBone.parentBoneIndex == -1)
                {
                    bindPoseInfos[index].LocalTransform = bindPoseInfos[index].AbsoluteTransform.Multiply(skinInitMatrix.Inverse);
                }
                else
                {
                    var parentBindPoseInfos = bindPoseInfos[babBone.parentBoneIndex];
                    bindPoseInfos[index].LocalTransform = bindPoseInfos[index].AbsoluteTransform.Multiply(parentBindPoseInfos.AbsoluteTransform.Inverse);
                }
                babBone.matrix = bindPoseInfos[index].LocalTransform.ToArray();

                var babylonAnimation = new BabylonAnimation
                {
                    name           = gameBone.Name + "Animation",
                    property       = "_matrix",
                    dataType       = (int)BabylonAnimation.DataType.Matrix,
                    loopBehavior   = (int)BabylonAnimation.LoopBehavior.Cycle,
                    framePerSecond = Loader.Global.FrameRate
                };

                var start = Loader.Core.AnimRange.Start;
                var end   = Loader.Core.AnimRange.End;

                float[] previous = null;
                var     keys     = new List <BabylonAnimationKey>();
                for (var key = start; key <= end; key += Ticks)
                {
                    var      objectTM   = gameBone.GetObjectTM(key);
                    var      parentNode = gameBone.NodeParent;
                    IGMatrix mat;
                    if (parentNode == null || babBone.parentBoneIndex == -1)
                    {
                        mat = objectTM.Multiply(meshNode.GetObjectTM(key).Inverse);
                    }
                    else
                    {
                        mat = objectTM.Multiply(parentNode.GetObjectTM(key).Inverse);
                    }

                    var current = mat.ToArray();
                    if (key == start || key == end || exportNonOptimizedAnimations || !(previous.IsEqualTo(current)))
                    {
                        keys.Add(new BabylonAnimationKey
                        {
                            frame  = key / Ticks,
                            values = current
                        });
                    }

                    previous = current;
                }

                babylonAnimation.keys = keys.ToArray();
                babBone.animation     = babylonAnimation;
            }

            babylonSkeleton.bones = bones.ToArray();

            babylonScene.SkeletonsList.Add(babylonSkeleton);
        }
Example #12
0
        /// <summary>
        /// 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)
        /// So to correct this difference, this function apply a rotation to the camera and its first children.
        /// </summary>
        /// <param name="camera"></param>
        /// <param name="babylonScene">Use the exported babylon scene to get the final hierarchy</param>
        private void FixCamera(ref BabylonCamera camera, ref BabylonScene babylonScene)
        {
            RaiseMessage("Start fix camera", 2);
            string id = camera.id;
            IList <BabylonMesh> meshes = babylonScene.MeshesList.FindAll(mesh => mesh.parentId == null ? false : mesh.parentId.Equals(id));

            RaiseMessage($"{camera.name}", 2);

            if (camera.target == null)
            {
                // fix the vue
                // Rotation around the axis X of PI / 2 in the indirect direction
                double angle = Math.PI / 2;
                if (camera.rotation != null)
                {
                    camera.rotation[0] += (float)angle;
                }
                if (camera.rotationQuaternion != null)
                {
                    BabylonQuaternion rotationQuaternion = FixCameraQuaternion(camera, angle);

                    camera.rotationQuaternion = rotationQuaternion.ToArray();
                    camera.rotation           = rotationQuaternion.toEulerAngles().ToArray();
                }

                BabylonAnimation animationRotationQuaternion;

                // animation
                if (camera.animations != null)
                {
                    List <BabylonAnimation> animations = new List <BabylonAnimation>(camera.animations);
                    animationRotationQuaternion = animations.Find(animation => animation.property.Equals("rotationQuaternion"));
                    if (animationRotationQuaternion != null)
                    {
                        foreach (BabylonAnimationKey key in animationRotationQuaternion.keys)
                        {
                            key.values = FixCameraQuaternion(key.values, angle);
                        }
                    }
                }

                // if the camera has a lockedTargetId, it is the extraAnimations that stores the rotation animation
                if (camera.extraAnimations != null)
                {
                    List <BabylonAnimation> extraAnimations = new List <BabylonAnimation>(camera.extraAnimations);
                    animationRotationQuaternion = extraAnimations.Find(animation => animation.property.Equals("rotationQuaternion"));
                    if (animationRotationQuaternion != null)
                    {
                        foreach (BabylonAnimationKey key in animationRotationQuaternion.keys)
                        {
                            key.values = FixCameraQuaternion(key.values, angle);
                        }
                    }
                }

                // fix direct children
                // Rotation around the axis X of -PI / 2 in the direct direction
                angle = -Math.PI / 2;
                foreach (var mesh in meshes)
                {
                    RaiseVerbose($"{mesh.name}", 3);
                    mesh.position = new float[] { mesh.position[0], mesh.position[2], -mesh.position[1] };

                    // Add a rotation of PI/2 axis X in direct direction
                    if (mesh.rotationQuaternion != null)
                    {
                        // Rotation around the axis X of -PI / 2 in the direct direction
                        BabylonQuaternion quaternion = FixChildQuaternion(mesh, angle);

                        mesh.rotationQuaternion = quaternion.ToArray();
                    }
                    if (mesh.rotation != null)
                    {
                        mesh.rotation[0] += (float)angle;
                    }


                    // Animations
                    if (mesh.animations != null)
                    {
                        List <BabylonAnimation> animations = new List <BabylonAnimation>(mesh.animations);
                        // Position
                        BabylonAnimation animationPosition = animations.Find(animation => animation.property.Equals("position"));
                        if (animationPosition != null)
                        {
                            foreach (BabylonAnimationKey key in animationPosition.keys)
                            {
                                key.values = new float[] { key.values[0], key.values[2], -key.values[1] };
                            }
                        }

                        // Rotation
                        animationRotationQuaternion = animations.Find(animation => animation.property.Equals("rotationQuaternion"));
                        if (animationRotationQuaternion != null)
                        {
                            foreach (BabylonAnimationKey key in animationRotationQuaternion.keys)
                            {
                                key.values = FixChildQuaternion(key.values, angle);
                            }
                        }
                    }
                }
            }
        }
Example #13
0
        public void Export(string outputDirectory, string outputFileName, string outputFormat, bool generateManifest,
                           bool onlySelected, bool autoSaveMayaFile, bool exportHiddenObjects, bool copyTexturesToOutput,
                           bool optimizeVertices, bool exportTangents, string scaleFactor, bool exportSkin, string quality, bool dracoCompression,
                           bool exportMorphNormal, bool exportMorphTangent)
        {
            // Check if the animation is running
            MGlobal.executeCommand("play -q - state", out int isPlayed);
            if (isPlayed == 1)
            {
                RaiseError("Stop the animation before exporting.");
                return;
            }

            // Check input text is valid
            var scaleFactorFloat = 1.0f;

            try
            {
                scaleFactor      = scaleFactor.Replace(".", System.Globalization.NumberFormatInfo.CurrentInfo.NumberDecimalSeparator);
                scaleFactor      = scaleFactor.Replace(",", System.Globalization.NumberFormatInfo.CurrentInfo.NumberDecimalSeparator);
                scaleFactorFloat = float.Parse(scaleFactor);
            }
            catch
            {
                RaiseError("Scale factor is not a valid number.");
                return;
            }

            try
            {
                _quality = long.Parse(quality);

                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 set the quality of jpg compression.");
                return;
            }

            RaiseMessage("Exportation started", Color.Blue);
            var progression = 0.0f;

            ReportProgressChanged(progression);

            // Store export options
            _onlySelected        = onlySelected;
            _exportHiddenObjects = exportHiddenObjects;
            _optimizeVertices    = optimizeVertices;
            _exportTangents      = exportTangents;
            CopyTexturesToOutput = copyTexturesToOutput;
            isBabylonExported    = outputFormat == "babylon" || outputFormat == "binary babylon";
            _exportSkin          = exportSkin;
            _dracoCompression    = dracoCompression;
            _exportMorphNormal   = exportMorphNormal;
            _exportMorphTangent  = exportMorphTangent;

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

            var watch = new Stopwatch();

            watch.Start();

            var outputBabylonDirectory = outputDirectory;
            var babylonScene           = new BabylonScene(outputBabylonDirectory);

            // Save scene
            if (autoSaveMayaFile)
            {
                RaiseMessage("Saving Maya file");

                // Query expand file name
                string fileName = MGlobal.executeCommandStringResult($@"file -q -exn;");

                // If scene has already been saved previously
                if (fileName.EndsWith(".ma") || fileName.EndsWith(".mb"))
                {
                    // Name is already specified and this line will not fail
                    MFileIO.save();
                }
                else
                {
                    // Open SaveAs dialog window
                    MGlobal.executeCommand($@"fileDialog2;");
                }
            }

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

            // Store selected nodes
            MSelectionList selectedNodes = new MSelectionList();

            MGlobal.getActiveSelectionList(selectedNodes);
            selectedNodeFullPaths = new List <string>();
            MItSelectionList mItSelectionList = new MItSelectionList(selectedNodes);

            while (!mItSelectionList.isDone)
            {
                MDagPath mDagPath = new MDagPath();
                try
                {
                    mItSelectionList.getDagPath(mDagPath);
                    selectedNodeFullPaths.Add(mDagPath.fullPathName);
                } catch
                {
                    // selected object is not a DAG object
                    // fail silently
                }

                mItSelectionList.next();
            }
            if (selectedNodeFullPaths.Count > 0)
            {
                RaiseMessage("Selected nodes full path");
                foreach (string selectedNodeFullPath in selectedNodeFullPaths)
                {
                    RaiseMessage(selectedNodeFullPath, 1);
                }
            }

            // Producer
            babylonScene.producer = new BabylonProducer
            {
                name             = "Maya",
                version          = "2018",
                exporter_version = exporterVersion,
                file             = outputFileName
            };

            // Global
            babylonScene.autoClear = true;
            // TODO - Retreive colors from Maya
            //babylonScene.clearColor = Loader.Core.GetBackGround(0, Tools.Forever).ToArray();
            //babylonScene.ambientColor = Loader.Core.GetAmbient(0, Tools.Forever).ToArray();

            // TODO - Add custom properties
            _exportQuaternionsInsteadOfEulers = true;

            PrintDAG(true);
            PrintDAG(false);

            // Store the current frame. It can be change to find a proper one for the node/bone export
            double currentTime = Loader.GetCurrentTime();

            // --------------------
            // ------ Nodes -------
            // --------------------
            RaiseMessage("Exporting nodes");

            // It makes each morph target manager export starts from id = 0.
            BabylonMorphTargetManager.Reset();

            // Clear materials
            referencedMaterials.Clear();
            multiMaterials.Clear();

            // Get all nodes
            var             dagIterator = new MItDag(MItDag.TraversalType.kDepthFirst, MFn.Type.kTransform);
            List <MDagPath> nodes       = new List <MDagPath>();

            while (!dagIterator.isDone)
            {
                MDagPath mDagPath = new MDagPath();
                dagIterator.getPath(mDagPath);

                // Check if one of its descendant (direct or not) is a mesh/camera/light/locator
                if (isNodeRelevantToExportRec(mDagPath)
                    // Ensure it's not one of the default cameras used as viewports in Maya
                    && defaultCameraNames.Contains(mDagPath.partialPathName) == false)
                {
                    nodes.Add(mDagPath);
                }
                else
                {
                    // Skip descendants
                    dagIterator.prune();
                }

                dagIterator.next();
            }
            // Export all nodes
            var progressionStep = 100.0f / nodes.Count;

            foreach (MDagPath mDagPath in nodes)
            {
                BabylonNode babylonNode = null;

                switch (getApiTypeOfDirectDescendants(mDagPath))
                {
                case MFn.Type.kMesh:
                    babylonNode = ExportMesh(mDagPath, babylonScene);
                    break;

                case MFn.Type.kCamera:
                    babylonNode = ExportCamera(mDagPath, babylonScene);
                    break;

                case MFn.Type.kLight:     // Lights api type are actually kPointLight, kSpotLight...
                    babylonNode = ExportLight(mDagPath, babylonScene);
                    break;

                case MFn.Type.kLocator:     // Camera target
                    babylonNode = ExportDummy(mDagPath, babylonScene);
                    break;
                }

                // If node is not exported successfully
                if (babylonNode == null)
                {
                    // Create a dummy (empty mesh)
                    babylonNode = ExportDummy(mDagPath, babylonScene);
                }
                ;

                // Update progress bar
                progression += progressionStep;
                ReportProgressChanged(progression);

                CheckCancelled();
            }
            RaiseMessage(string.Format("Total meshes: {0}", babylonScene.MeshesList.Count), Color.Gray, 1);


            // if nothing is enlightened, exclude all meshes
            foreach (BabylonLight light in babylonScene.LightsList)
            {
                if (light.includedOnlyMeshesIds.Length == 0)
                {
                    light.excludedMeshesIds = babylonScene.MeshesList.Select(m => m.id).ToArray();
                }
            }

            /*
             * Switch coordinate system at global level
             *
             * Add a root node with negative scaling
             * Pros - It's safer to use a root node
             * Cons - It's cleaner to switch at object level (as it is done now)
             * Use root node method when you want to be 100% sure of the output
             * Don't forget to also inverse winding order of mesh indices
             */
            //// Switch from right to left handed coordinate system
            //MUuid mUuid = new MUuid();
            //mUuid.generate();
            //var rootNode = new BabylonMesh
            //{
            //    name = "root",
            //    id = mUuid.asString(),
            //    scaling = new float[] { 1, 1, -1 }
            //};
            //foreach(var babylonMesh in babylonScene.MeshesList)
            //{
            //    // Add root meshes as child to root node
            //    if (babylonMesh.parentId == null)
            //    {
            //        babylonMesh.parentId = rootNode.id;
            //    }
            //}
            //babylonScene.MeshesList.Add(rootNode);

            // Main camera
            BabylonCamera babylonMainCamera = null;

            if (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);
            }

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

            // Default light
            if (babylonScene.LightsList.Count == 0)
            {
                RaiseWarning("No light defined", 1);
                RaiseWarning("A default ambient 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 = Tools.GenerateUUID()
                };
                rootNode.isDummy = true;
                float rootNodeScale = 1.0f / scaleFactorFloat;
                rootNode.scaling = new float[3] {
                    rootNodeScale, rootNodeScale, rootNodeScale
                };

                // 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 ----
            // --------------------
            RaiseMessage("Exporting materials");
            GenerateMaterialDuplicationDatas(babylonScene);
            foreach (var mat in referencedMaterials)
            {
                ExportMaterial(mat, babylonScene);
                CheckCancelled();
            }
            foreach (var mat in multiMaterials)
            {
                ExportMultiMaterial(mat.Key, mat.Value, babylonScene);
                CheckCancelled();
            }
            UpdateMeshesMaterialId(babylonScene);
            RaiseMessage(string.Format("Total: {0}", babylonScene.MaterialsList.Count + babylonScene.MultiMaterialsList.Count), Color.Gray, 1);


            // Export skeletons
            if (_exportSkin && skins.Count > 0)
            {
                progressSkin     = 0;
                progressSkinStep = 100 / skins.Count;
                ReportProgressChanged(progressSkin);
                RaiseMessage("Exporting skeletons");
                foreach (var skin in skins)
                {
                    ExportSkin(skin, babylonScene);
                }
            }

            // set back the frame
            Loader.SetCurrentTime(currentTime);

            // Animation group
            if (isBabylonExported)
            {
                RaiseMessage("Export animation groups");
                // add animation groups to the scene
                babylonScene.animationGroups = ExportAnimationGroups(babylonScene);

                // if there is animationGroup, then remove animations from nodes
                if (babylonScene.animationGroups.Count > 0)
                {
                    // add animations of each nodes in the animGroup
                    List <BabylonNode> babylonNodes = new List <BabylonNode>();
                    babylonNodes.AddRange(babylonScene.MeshesList);
                    babylonNodes.AddRange(babylonScene.CamerasList);
                    babylonNodes.AddRange(babylonScene.LightsList);

                    foreach (BabylonNode node in babylonNodes)
                    {
                        node.animations = null;
                    }
                    foreach (BabylonSkeleton skel in babylonScene.SkeletonsList)
                    {
                        foreach (BabylonBone bone in skel.bones)
                        {
                            bone.animation = null;
                        }
                    }
                }
            }


            // Output
            babylonScene.Prepare(false, false);
            if (isBabylonExported)
            {
                Write(babylonScene, outputBabylonDirectory, outputFileName, outputFormat, generateManifest);
            }

            ReportProgressChanged(100);

            // Export glTF
            if (outputFormat == "gltf" || outputFormat == "glb")
            {
                bool generateBinary = outputFormat == "glb";
                ExportGltf(babylonScene, outputDirectory, outputFileName, generateBinary);
            }

            watch.Stop();
            RaiseMessage(string.Format("Exportation done in {0:0.00}s", watch.ElapsedMilliseconds / 1000.0), Color.Blue);
        }
        private GLTFNode ExportAbstractMesh(BabylonAbstractMesh babylonAbstractMesh, GLTF gltf, GLTFNode gltfParentNode, BabylonScene babylonScene)
        {
            RaiseMessage("GLTFExporter.AbstractMesh | Export abstract mesh named: " + babylonAbstractMesh.name, 1);

            // Node
            var gltfNode = new GLTFNode();

            gltfNode.name  = babylonAbstractMesh.name;
            gltfNode.index = gltf.NodesList.Count;
            gltf.NodesList.Add(gltfNode);

            // Hierarchy
            if (gltfParentNode != null)
            {
                RaiseMessage("GLTFExporter.AbstractMesh | Add " + babylonAbstractMesh.name + " as child to " + gltfParentNode.name, 2);
                gltfParentNode.ChildrenList.Add(gltfNode.index);
                gltfNode.parent = gltfParentNode;
            }
            else
            {
                // It's a root node
                // Only root nodes are listed in a gltf scene
                RaiseMessage("GLTFExporter.AbstractMesh | Add " + babylonAbstractMesh.name + " as root node to scene", 2);
                gltf.scenes[0].NodesList.Add(gltfNode.index);
            }

            // Transform
            gltfNode.translation = babylonAbstractMesh.position;
            if (babylonAbstractMesh.rotationQuaternion != null)
            {
                gltfNode.rotation = babylonAbstractMesh.rotationQuaternion;
            }
            else
            {
                // Convert rotation vector to quaternion
                BabylonVector3 rotationVector3 = new BabylonVector3
                {
                    X = babylonAbstractMesh.rotation[0],
                    Y = babylonAbstractMesh.rotation[1],
                    Z = babylonAbstractMesh.rotation[2]
                };
                gltfNode.rotation = rotationVector3.toQuaternion().ToArray();
            }
            gltfNode.scale = babylonAbstractMesh.scaling;

            // Mesh
            var gltfMesh = gltf.MeshesList.Find(_gltfMesh => _gltfMesh.idGroupInstance == babylonAbstractMesh.idGroupInstance);

            if (gltfMesh != null)
            {
                gltfNode.mesh = gltfMesh.index;

                // Skin
                if (gltfMesh.idBabylonSkeleton.HasValue)
                {
                    var babylonSkeleton = babylonScene.skeletons[gltfMesh.idBabylonSkeleton.Value];
                    // Export a new skin and a new skeleton
                    // TODO - Use the skeleton if already exported and only create a new skin
                    var gltfSkin = ExportSkin(babylonSkeleton, gltf, gltfNode);
                    gltfNode.skin = gltfSkin.index;
                }
            }

            // Animations
            ExportNodeAnimation(babylonAbstractMesh, gltf, gltfNode, babylonScene);

            return(gltfNode);
        }
Example #15
0
        private void ExportSkin(IIGameSkin skin, BabylonScene babylonScene)
        {
            var babylonSkeleton = new BabylonSkeleton {
                id = skins.IndexOf(skin)
            };

            babylonSkeleton.name = "skeleton #" + babylonSkeleton.id;

            RaiseMessage(babylonSkeleton.name, 1);

            var skinIndex = skins.IndexOf(skin);

            var bones         = new List <BabylonBone>();
            var gameBones     = new List <IIGameNode>();
            var boneIds       = new List <int>();
            var bindPoseInfos = new List <BonePoseInfo>();

            for (int i = 0; i < skin.TotalSkinBoneCount; ++i)
            {
                bones.Add(null);
                gameBones.Add(null);
                boneIds.Add(-1);
                bindPoseInfos.Add(null);
            }
            for (var index = 0; index < skin.TotalSkinBoneCount; index++)
            {
                var gameBone = skin.GetIGameBone(index, false);

                var sortedIndex = skinSortedBones[skin].IndexOf(gameBone.NodeID);

                gameBones[sortedIndex] = (gameBone);
                boneIds[sortedIndex]   = (gameBone.NodeID);
                bones[sortedIndex]     = (new BabylonBone {
                    index = sortedIndex, name = gameBone.Name, id = gameBone.MaxNode.GetGuid().ToString()
                });

                var boneInitMatrix = gameBone.GetObjectTM(0);
                bindPoseInfos[sortedIndex] = (new BonePoseInfo {
                    AbsoluteTransform = boneInitMatrix
                });
            }

            // fix hierarchy and generate animation keys
            for (var index = 0; index < skin.TotalSkinBoneCount; index++)
            {
                var gameBone = gameBones[index];
                var parent   = gameBone.NodeParent;
                var babBone  = bones[index];
                if (parent != null)
                {
                    babBone.parentBoneIndex = boneIds.IndexOf(parent.NodeID);
                }

                if (babBone.parentBoneIndex == -1)
                {
                    bindPoseInfos[index].LocalTransform = bindPoseInfos[index].AbsoluteTransform;
                }
                else
                {
                    var parentBindPoseInfos = bindPoseInfos[babBone.parentBoneIndex];
                    bindPoseInfos[index].LocalTransform = bindPoseInfos[index].AbsoluteTransform.Multiply(parentBindPoseInfos.AbsoluteTransform.Inverse);
                }

                babBone.matrix = bindPoseInfos[index].LocalTransform.ToArray();

                var babylonAnimation = ExportMatrixAnimation("_matrix", key =>
                {
                    var objectTM   = gameBone.GetObjectTM(key);
                    var parentNode = gameBone.NodeParent;
                    IGMatrix mat;
                    if (parentNode == null || babBone.parentBoneIndex == -1)
                    {
                        mat = objectTM;
                    }
                    else
                    {
                        mat = objectTM.Multiply(parentNode.GetObjectTM(key).Inverse);
                    }
                    return(mat.ToArray());
                },
                                                             false); // Do not remove linear animation keys for bones

                if (babylonAnimation != null)
                {
                    babylonAnimation.name = gameBone.Name + "Animation"; // override default animation name
                    babBone.animation     = babylonAnimation;
                }
            }

            babylonSkeleton.needInitialSkinMatrix = true;
            babylonSkeleton.bones = bones.ToArray();

            babylonScene.SkeletonsList.Add(babylonSkeleton);
        }
Example #16
0
        // -------------------------
        // -- Export sub methods ---
        // -------------------------

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

            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 = 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 babylonTexture = new BabylonTexture
            {
                name = Path.GetFileNameWithoutExtension(texture.MapName) + "." + validImageFormat
            };

            // 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);
                CopyTexture(sourcePath, destPath);

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

            return(babylonTexture);
        }
Example #17
0
        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) : ColorToStringName(specularColor)) +
                       Path.GetFileNameWithoutExtension(specularLevelTexture.Map.FullFilePath) + "_specularColor";

            var babylonTexture = new BabylonTexture
            {
                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 = _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);
                    SaveBitmap(specularColorPreMultipliedBitmap, babylonScene.OutputPath, babylonTexture.name, ImageFormat.Jpeg);
                }
                else
                {
                    // Store created bitmap for further use in gltf export
                    babylonTexture.bitmap = specularColorPreMultipliedBitmap;
                }
            }

            return(babylonTexture);
        }
Example #18
0
        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 babylonTexture = new BabylonTexture
            {
                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 = _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);
                    SaveBitmap(ormBitmap, babylonScene.OutputPath, babylonTexture.name, ImageFormat.Jpeg);
                }
                else
                {
                    // Store created bitmap for further use in gltf export
                    babylonTexture.bitmap = ormBitmap;
                }
            }

            return(babylonTexture);
        }
Example #19
0
        private BabylonCamera ExportCamera(IIGameScene scene, IIGameNode cameraNode, BabylonScene babylonScene)
        {
            if (IsCameraExportable(cameraNode) == false)
            {
                return(null);
            }

            var gameCamera    = cameraNode.IGameObject.AsGameCamera();
            var maxCamera     = gameCamera.MaxObject as ICameraObject;
            var initialized   = gameCamera.InitializeData;
            var babylonCamera = new BabylonCamera();

            RaiseMessage(cameraNode.Name, 1);
            babylonCamera.name = cameraNode.Name;
            babylonCamera.id   = cameraNode.MaxNode.GetGuid().ToString();
            if (cameraNode.NodeParent != null)
            {
                babylonCamera.parentId = cameraNode.NodeParent.MaxNode.GetGuid().ToString();
            }

            // Export the custom attributes of this camera
            babylonCamera.metadata = ExportExtraAttributes(cameraNode, babylonScene);

            babylonCamera.fov = Tools.ConvertFov(maxCamera.GetFOV(0, Tools.Forever));

            if (maxCamera.ManualClip == 1)
            {
                babylonCamera.minZ = maxCamera.GetClipDist(0, 1, Tools.Forever);
                babylonCamera.maxZ = maxCamera.GetClipDist(0, 2, Tools.Forever);
            }
            else
            {
                babylonCamera.minZ = 0.1f;
                babylonCamera.maxZ = 10000.0f;
            }

            if (babylonCamera.minZ == 0.0f)
            {
                babylonCamera.minZ = 0.1f;
            }

            // Type
            babylonCamera.type = cameraNode.MaxNode.GetStringProperty("babylonjs_type", "FreeCamera");

            // Control
            babylonCamera.speed   = cameraNode.MaxNode.GetFloatProperty("babylonjs_speed", 1.0f);
            babylonCamera.inertia = cameraNode.MaxNode.GetFloatProperty("babylonjs_inertia", 0.9f);

            // Collisions
            babylonCamera.checkCollisions = cameraNode.MaxNode.GetBoolProperty("babylonjs_checkcollisions");
            babylonCamera.applyGravity    = cameraNode.MaxNode.GetBoolProperty("babylonjs_applygravity");
            babylonCamera.ellipsoid       = cameraNode.MaxNode.GetVector3Property("babylonjs_ellipsoid");

            // Position / rotation
            exportTransform(babylonCamera, cameraNode);

            // Target
            var target = gameCamera.CameraTarget;

            if (target != null)
            {
                babylonCamera.lockedTargetId = target.MaxNode.GetGuid().ToString();
            }

            if (exportParameters.exportAnimations)
            {
                // Animations
                var animations = new List <BabylonAnimation>();

                GeneratePositionAnimation(cameraNode, animations);

                if (target == null)
                {
                    // Export rotation animation
                    GenerateRotationAnimation(cameraNode, animations);
                }
                else
                {
                    // Animation temporary stored for gltf but not exported for babylon
                    // TODO - Will cause an issue when externalizing the glTF export process
                    var extraAnimations = new List <BabylonAnimation>();
                    // Do not check if node rotation properties are animated
                    GenerateRotationAnimation(cameraNode, extraAnimations, true);
                    babylonCamera.extraAnimations = extraAnimations;
                }

                ExportFloatAnimation("fov", animations, key => new[] { Tools.ConvertFov((gameCamera.MaxObject as ICameraObject).GetFOV(key, Tools.Forever)) });

                babylonCamera.animations = animations.ToArray();

                if (cameraNode.MaxNode.GetBoolProperty("babylonjs_autoanimate"))
                {
                    babylonCamera.autoAnimate     = true;
                    babylonCamera.autoAnimateFrom = (int)cameraNode.MaxNode.GetFloatProperty("babylonjs_autoanimate_from");
                    babylonCamera.autoAnimateTo   = (int)cameraNode.MaxNode.GetFloatProperty("babylonjs_autoanimate_to");
                    babylonCamera.autoAnimateLoop = cameraNode.MaxNode.GetBoolProperty("babylonjs_autoanimateloop");
                }
            }

            babylonScene.CamerasList.Add(babylonCamera);

            return(babylonCamera);
        }
Example #20
0
        void DumpLights(NovaScene scene, BabylonScene babylonScene)
        {
            foreach (NovaLight light in scene.Lights)
            {
                if (light.Enabled)
                {
                    var babylonLight = new BabylonLight();
                    babylonScene.LightsList.Add(babylonLight);

                    babylonLight.name = light.Name;
                    babylonLight.id = light.ID.ToString();
                    switch (light.Type)
                    {
                        case NovaLightType.Point:
                            babylonLight.type = 0;
                            babylonLight.position = light.Position.ToArray();
                            break;
                        case NovaLightType.Spot:
                        case NovaLightType.Directional:
                            babylonLight.type = 1;
                            babylonLight.position = light.Position.ToArray();
                            babylonLight.direction = light.Direction.ToArray();
                            break;
                    }
                    babylonLight.diffuse = light.Diffuse.ToArray();
                    babylonLight.specular = light.Specular.ToArray();
                    babylonLight.intensity = light.Multiplicator;

                    if (light.ShadowMembers.Count > 0)
                    {
                        var shadowGenerator = new BabylonShadowGenerator
                        {
                            useVarianceShadowMap = true,
                            lightId = light.ID.ToString(),
                            mapSize = light.ShadowMapSize,
                            renderList = light.ShadowMembers.Select(m => m.ID.ToString()).ToArray()
                        };
                        babylonScene.ShadowGeneratorsList.Add(shadowGenerator);
                    }

                    if (light.LensFlares != null)
                    {
                        light.LensFlares.Tag = light;
                        lensFlareSystemToExport.Add(light.LensFlares);
                    }
                }
            }
        }
        private void ExportAnimationGroups(GLTF gltf, BabylonScene babylonScene)
        {
            // Retreive and parse animation group data
            var animationGroupList  = babylonScene.animationGroups;
            var animationGroupCount = animationGroupList == null ? 0 : animationGroupList.Count;

            gltf.AnimationsList.Clear();
            gltf.AnimationsList.Capacity = Math.Max(gltf.AnimationsList.Capacity, animationGroupCount);

            if (animationGroupCount <= 0)
            {
                logger.RaiseMessage("GLTFExporter.Animation | No AnimationGroups: exporting all animations together.", 1);
                GLTFAnimation gltfAnimation = new GLTFAnimation();
                gltfAnimation.name = "All Animations";

                int startFrame = babylonScene.TimelineStartFrame;
                int endFrame   = babylonScene.TimelineEndFrame;

                foreach (var pair in nodeToGltfNodeMap)
                {
                    BabylonNode node                             = pair.Key;
                    GLTFNode    gltfNode                         = pair.Value;
                    bool        nodeHasAnimations                = node.animations != null && node.animations.Length > 0 && node.animations[0] != null;
                    bool        nodeHasExtraAnimations           = node.extraAnimations != null && node.extraAnimations.Count > 0 && node.extraAnimations[0] != null;
                    BabylonMesh meshNode                         = node as BabylonMesh;
                    BabylonMorphTargetManager morphTargetManager = null;
                    bool nodeHasAnimatedMorphTargets             = false;
                    if (meshNode != null && meshNode.morphTargetManagerId != null)
                    {
                        morphTargetManager = GetBabylonMorphTargetManager(babylonScene, meshNode);
                        if (morphTargetManager != null)
                        {
                            nodeHasAnimatedMorphTargets = morphTargetManager.targets.Any(target => target.animations != null && target.animations.Length > 0 && target.animations[0] != null);
                        }
                    }

                    if (!nodeHasAnimations && !nodeHasExtraAnimations && !nodeHasAnimatedMorphTargets)
                    {
                        continue;
                    }
                    if (nodeHasAnimations && node.animations[0].property == "_matrix")
                    {
                        ExportBoneAnimation(gltfAnimation, startFrame, endFrame, gltf, node, pair.Value);
                    }
                    else
                    {
                        ExportNodeAnimation(gltfAnimation, startFrame, endFrame, gltf, node, gltfNode, babylonScene);
                    }

                    if (nodeHasAnimatedMorphTargets)
                    {
                        ExportMorphTargetWeightAnimation(morphTargetManager, gltf, gltfNode, gltfAnimation.ChannelList, gltfAnimation.SamplerList, startFrame, endFrame, babylonScene);
                    }
                }

                if (gltfAnimation.ChannelList.Count > 0)
                {
                    gltf.AnimationsList.Add(gltfAnimation);
                }
                else
                {
                    logger.RaiseMessage("GLTFExporter.Animation | No animation data for this animation, it is ignored.", 2);
                }
            }
            else
            {
                foreach (BabylonAnimationGroup animGroup in animationGroupList)
                {
                    logger.RaiseMessage("GLTFExporter.Animation | " + animGroup.name, 1);

                    GLTFAnimation gltfAnimation = new GLTFAnimation();
                    gltfAnimation.name = animGroup.name;

                    int startFrame = MathUtilities.RoundToInt(animGroup.from);
                    int endFrame   = MathUtilities.RoundToInt(animGroup.to);

                    var uniqueNodeIds = animGroup.targetedAnimations.Select(targetAnim => targetAnim.targetId).Distinct();
                    foreach (var id in uniqueNodeIds)
                    {
                        BabylonNode babylonNode = babylonNodes.Find(node => node.id.Equals(id));
                        GLTFNode    gltfNode    = null;
                        // search the babylon scene id map for the babylon node that matches this id
                        if (babylonNode != null)
                        {
                            BabylonMorphTargetManager morphTargetManager = null;

                            // search our babylon->gltf node mapping to see if this node is included in the exported gltf scene
                            if (!nodeToGltfNodeMap.TryGetValue(babylonNode, out gltfNode))
                            {
                                continue;
                            }

                            bool nodeHasAnimations      = babylonNode.animations != null && babylonNode.animations.Length > 0 && babylonNode.animations[0] != null;
                            bool nodeHasExtraAnimations = babylonNode.extraAnimations != null && babylonNode.extraAnimations.Count > 0 && babylonNode.extraAnimations[0] != null;
                            if (!nodeHasAnimations && !nodeHasExtraAnimations)
                            {
                                continue;
                            }

                            if (nodeHasAnimations && babylonNode.animations[0].property == "_matrix") //TODO: Is this check accurate for deciphering between bones and nodes?
                            {
                                ExportBoneAnimation(gltfAnimation, startFrame, endFrame, gltf, babylonNode, gltfNode);
                            }
                            else
                            {
                                ExportNodeAnimation(gltfAnimation, startFrame, endFrame, gltf, babylonNode, gltfNode, babylonScene);
                            }
                        }
                        else
                        {
                            // if the node isn't found in the scene id map, check if it is the id for a morph target
                            BabylonMorphTargetManager morphTargetManager = babylonScene.morphTargetManagers.FirstOrDefault(mtm => mtm.targets.Any(target => target.animations != null && target.animations.Length > 0 && target.animations[0] != null));
                            if (morphTargetManager != null)
                            {
                                BabylonMesh mesh = morphTargetManager.sourceMesh;
                                if (mesh != null && nodeToGltfNodeMap.TryGetValue(mesh, out gltfNode))
                                {
                                    ExportMorphTargetWeightAnimation(morphTargetManager, gltf, gltfNode, gltfAnimation.ChannelList, gltfAnimation.SamplerList, startFrame, endFrame, babylonScene);
                                }
                            }
                        }
                    }

                    if (gltfAnimation.ChannelList.Count > 0)
                    {
                        gltf.AnimationsList.Add(gltfAnimation);
                    }
                    else
                    {
                        logger.RaiseMessage("No data exported for this animation, it is ignored.", 2);
                    }
                    // clear the exported morph target cache, since we are exporting a new animation group. //TODO: we should probably do this more elegantly.
                    exportedMorphTargets.Clear();
                }
            }
        }
        private BabylonTexture ExportTexture(IStdMat2 stdMat, int index, out BabylonFresnelParameters fresnelParameters, BabylonScene babylonScene, bool allowCube = false, bool forceAlpha = false)
        {
            fresnelParameters = null;

            if (!stdMat.MapEnabled(index))
            {
                return(null);
            }
            var babylonTexture = new BabylonTexture();

            var texMap = stdMat.GetSubTexmap(index);

            if (texMap == null)
            {
                RaiseWarning("Texture channel " + index + " activated but no texture found.");
                return(null);
            }

            // Fallout
            if (texMap.ClassName == "Falloff") // This is the only way I found to detect it. This is crappy but it works
            {
                fresnelParameters = new BabylonFresnelParameters();

                var paramBlock = texMap.GetParamBlock(0);
                var color1     = paramBlock.GetColor(0, 0, 0);
                var color2     = paramBlock.GetColor(4, 0, 0);

                fresnelParameters.isEnabled  = true;
                fresnelParameters.leftColor  = color2.ToArray();
                fresnelParameters.rightColor = color1.ToArray();

                if (paramBlock.GetInt(8, 0, 0) == 2)
                {
                    fresnelParameters.power = paramBlock.GetFloat(12, 0, 0);
                }
                else
                {
                    fresnelParameters.power = 1;
                }
                var texMap1   = paramBlock.GetTexmap(2, 0, 0);
                var texMap1On = paramBlock.GetInt(3, 0, 0);

                var texMap2   = paramBlock.GetTexmap(6, 0, 0);
                var texMap2On = paramBlock.GetInt(7, 0, 0);

                if (texMap1 != null && texMap1On != 0)
                {
                    texMap = texMap1;
                    fresnelParameters.rightColor = new float[] { 1, 1, 1 };

                    if (texMap2 != null && texMap2On != 0)
                    {
                        RaiseWarning(string.Format("You cannot specify two textures for falloff. Only one is supported"), 2);
                    }
                }
                else if (texMap2 != null && texMap2On != 0)
                {
                    fresnelParameters.leftColor = new float[] { 1, 1, 1 };
                    texMap = texMap2;
                }
                else
                {
                    return(null);
                }
            }

            // Bitmap
            if (texMap.GetParamBlock(0) == null || texMap.GetParamBlock(0).Owner == null)
            {
                return(null);
            }

            var texture = texMap.GetParamBlock(0).Owner as IBitmapTex;

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

            if (forceAlpha)
            {
                babylonTexture.hasAlpha        = true;
                babylonTexture.getAlphaFromRGB = (texture.AlphaSource == 2) || (texture.AlphaSource == 3);
            }
            else
            {
                babylonTexture.hasAlpha        = (texture.AlphaSource != 3);
                babylonTexture.getAlphaFromRGB = (texture.AlphaSource == 2);
            }


            babylonTexture.level = stdMat.GetTexmapAmt(index, 0);

            var uvGen = texture.UVGen;

            switch (uvGen.GetCoordMapping(0))
            {
            case 1:     //MAP_SPHERICAL
                babylonTexture.coordinatesMode = 1;
                break;

            case 2:     //MAP_PLANAR
                babylonTexture.coordinatesMode = 2;
                break;

            default:
                babylonTexture.coordinatesMode = 0;
                break;
            }

            babylonTexture.coordinatesIndex = uvGen.MapChannel - 1;
            if (uvGen.MapChannel > 2)
            {
                RaiseWarning(string.Format("Unsupported map channel, Only channel 1 and 2 are supported."), 2);
            }

            babylonTexture.uOffset = uvGen.GetUOffs(0);
            babylonTexture.vOffset = uvGen.GetVOffs(0);

            babylonTexture.uScale = uvGen.GetUScl(0);
            babylonTexture.vScale = uvGen.GetVScl(0);

            if (Path.GetExtension(texture.MapName).ToLower() == ".dds")
            {
                babylonTexture.vScale *= -1; // Need to invert Y-axis for DDS texture
            }

            babylonTexture.uAng = uvGen.GetUAng(0);
            babylonTexture.vAng = uvGen.GetVAng(0);
            babylonTexture.wAng = uvGen.GetWAng(0);

            babylonTexture.wrapU = 0;           // CLAMP
            if ((uvGen.TextureTiling & 1) != 0) // WRAP
            {
                babylonTexture.wrapU = 1;
            }
            else if ((uvGen.TextureTiling & 4) != 0) // MIRROR
            {
                babylonTexture.wrapU = 2;
            }

            babylonTexture.wrapV = 0;           // CLAMP
            if ((uvGen.TextureTiling & 2) != 0) // WRAP
            {
                babylonTexture.wrapV = 1;
            }
            else if ((uvGen.TextureTiling & 8) != 0) // MIRROR
            {
                babylonTexture.wrapV = 2;
            }

            babylonTexture.name = Path.GetFileName(texture.MapName);

            // 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();
            var absolutePath = texture.Map.FullFilePath;

            // Copy texture to output
            try
            {
                if (File.Exists(absolutePath))
                {
                    babylonTexture.isCube = IsTextureCube(absolutePath);
                    if (CopyTexturesToOutput)
                    {
                        File.Copy(absolutePath, Path.Combine(babylonScene.OutputPath, babylonTexture.name), true);
                    }
                }
                else
                {
                    RaiseWarning(string.Format("Texture {0} not found.", babylonTexture.name), 2);
                }
            }
            catch
            {
                // silently fails
            }

            if (babylonTexture.isCube && !allowCube)
            {
                RaiseWarning(string.Format("Cube texture are only supported for reflection channel"), 2);
            }

            return(babylonTexture);
        }
        private void ExportNodeAnimation(GLTFAnimation gltfAnimation, int startFrame, int endFrame, GLTF gltf, BabylonNode babylonNode, GLTFNode gltfNode, BabylonScene babylonScene)
        {
            var channelList = gltfAnimation.ChannelList;
            var samplerList = gltfAnimation.SamplerList;

            bool exportNonAnimated = exportParameters.animgroupExportNonAnimated;

            // Combine babylon animations from .babylon file and cached ones
            var babylonAnimations = new List <BabylonAnimation>();

            if (babylonNode.animations != null)
            {
                babylonAnimations.AddRange(babylonNode.animations);
            }
            if (babylonNode.extraAnimations != null)
            {
                babylonAnimations.AddRange(babylonNode.extraAnimations);
            }

            // Filter animations to only keep TRS ones
            babylonAnimations = babylonAnimations.FindAll(babylonAnimation => _getTargetPath(babylonAnimation.property) != null);

            if (babylonAnimations.Count > 0 || exportNonAnimated)
            {
                if (babylonAnimations.Count > 0)
                {
                    logger.RaiseMessage("GLTFExporter.Animation | Export animations of node named: " + babylonNode.name, 2);
                }
                else if (exportNonAnimated)
                {
                    logger.RaiseMessage("GLTFExporter.Animation | Export dummy animation for node named: " + babylonNode.name, 2);
                    // Export a dummy animation
                    babylonAnimations.Add(GetDummyAnimation(gltfNode, startFrame, endFrame, babylonScene));
                }


                foreach (BabylonAnimation babylonAnimation in babylonAnimations)
                {
                    var babylonAnimationKeysInRange = babylonAnimation.keys.Where(key => key.frame >= startFrame && key.frame <= endFrame);
                    if (babylonAnimationKeysInRange.Count() <= 0)
                    {
                        continue;
                    }

                    // Target
                    var gltfTarget = new GLTFChannelTarget
                    {
                        node = gltfNode.index
                    };
                    gltfTarget.path = _getTargetPath(babylonAnimation.property);

                    // --- Input ---
                    var accessorInput = _createAndPopulateInput(gltf, babylonAnimation, startFrame, endFrame);
                    if (accessorInput == null)
                    {
                        continue;
                    }

                    // --- Output ---
                    GLTFAccessor accessorOutput = _createAccessorOfPath(gltfTarget.path, gltf);

                    // Populate accessor
                    int numKeys = 0;
                    foreach (var babylonAnimationKey in babylonAnimationKeysInRange)
                    {
                        numKeys++;

                        // copy data before changing it in case animation groups overlap
                        float[] outputValues = new float[babylonAnimationKey.values.Length];
                        babylonAnimationKey.values.CopyTo(outputValues, 0);

                        // Switch coordinate system at object level
                        if (babylonAnimation.property == "position")
                        {
                            outputValues[2] *= -1;
                        }
                        else if (babylonAnimation.property == "rotationQuaternion")
                        {
                            outputValues[0] *= -1;
                            outputValues[1] *= -1;
                        }

                        // Store values as bytes
                        foreach (var outputValue in outputValues)
                        {
                            accessorOutput.bytesList.AddRange(BitConverter.GetBytes(outputValue));
                        }
                    }
                    ;
                    accessorOutput.count = numKeys;
                    if (accessorOutput.count == 0)
                    {
                        logger.RaiseWarning(String.Format("GLTFExporter.Animation | No frames to export in node animation \"{1}\" of node named \"{0}\". This will cause an error in the output gltf.", babylonNode.name, babylonAnimation.name));
                    }

                    // Animation sampler
                    var gltfAnimationSampler = new GLTFAnimationSampler
                    {
                        input  = accessorInput.index,
                        output = accessorOutput.index
                    };
                    gltfAnimationSampler.index = samplerList.Count;
                    samplerList.Add(gltfAnimationSampler);

                    // Channel
                    var gltfChannel = new GLTFChannel
                    {
                        sampler = gltfAnimationSampler.index,
                        target  = gltfTarget
                    };
                    channelList.Add(gltfChannel);
                }
            }

            ExportGLTFExtension(babylonNode, ref gltfAnimation, gltf);
        }
Example #24
0
        private BabylonLight ExportLight(IIGameScene scene, IIGameNode lightNode, BabylonScene babylonScene)
        {
            if (IsLightExportable(lightNode) == false)
            {
                return(null);
            }

            var gameLight    = lightNode.IGameObject.AsGameLight();
            var initialized  = gameLight.InitializeData;
            var babylonLight = new BabylonLight();

            RaiseMessage(lightNode.Name, 1);
            babylonLight.name = lightNode.Name;
            babylonLight.id   = lightNode.MaxNode.GetGuid().ToString();
            if (lightNode.NodeParent != null)
            {
                babylonLight.parentId = lightNode.NodeParent.MaxNode.GetGuid().ToString();
            }

            // Type

            var maxLight   = (lightNode.MaxNode.ObjectRef as ILightObject);
            var lightState = Loader.Global.LightState.Create();

            maxLight.EvalLightState(0, Tools.Forever, lightState);

            switch (lightState.Type)
            {
            case LightType.OmniLgt:
                babylonLight.type = 0;
                break;

            case LightType.SpotLgt:
                babylonLight.type     = 2;
                babylonLight.angle    = (float)(maxLight.GetFallsize(0, Tools.Forever) * Math.PI / 180.0f);
                babylonLight.exponent = 1;
                break;

            case LightType.DirectLgt:
                babylonLight.type = 1;
                break;

            case LightType.AmbientLgt:
                babylonLight.type        = 3;
                babylonLight.groundColor = new float[] { 0, 0, 0 };
                break;
            }


            // Shadows
            if (maxLight.ShadowMethod == 1)
            {
                if (lightState.Type == LightType.DirectLgt || lightState.Type == LightType.SpotLgt || lightState.Type == LightType.OmniLgt)
                {
                    ExportShadowGenerator(lightNode.MaxNode, babylonScene);
                }
                else
                {
                    RaiseWarning("Shadows maps are only supported for point, directional and spot lights", 2);
                }
            }

            // Position
            var localMatrix = lightNode.GetLocalTM(0);

            var position = localMatrix.Translation;

            babylonLight.position = new[] { position.X, position.Y, position.Z };

            // Direction
            var target = gameLight.LightTarget;

            if (target != null)
            {
                var targetWm       = target.GetObjectTM(0);
                var targetPosition = targetWm.Translation;

                var direction = targetPosition.Subtract(position).Normalize;
                babylonLight.direction = new[] { direction.X, direction.Y, direction.Z };
            }
            else
            {
                var vDir = Loader.Global.Point3.Create(0, -1, 0);
                vDir = localMatrix.ExtractMatrix3().VectorTransform(vDir).Normalize;
                babylonLight.direction = new[] { vDir.X, vDir.Y, vDir.Z };
            }

            var maxScene = Loader.Core.RootNode;

            // Exclusion
            try
            {
                var inclusion          = maxLight.ExclList.TestFlag(1); //NT_INCLUDE
                var checkExclusionList = maxLight.ExclList.TestFlag(2); //NT_AFFECT_ILLUM

                if (checkExclusionList)
                {
                    var excllist = new List <string>();
                    var incllist = new List <string>();

                    foreach (var meshNode in maxScene.NodesListBySuperClass(SClass_ID.Geomobject))
                    {
#if MAX2017 || MAX2018
                        if (meshNode.CastShadows)
#else
                        if (meshNode.CastShadows == 1)
#endif
                        {
                            var inList = maxLight.ExclList.FindNode(meshNode) != -1;

                            if (inList)
                            {
                                if (inclusion)
                                {
                                    incllist.Add(meshNode.GetGuid().ToString());
                                }
                                else
                                {
                                    excllist.Add(meshNode.GetGuid().ToString());
                                }
                            }
                        }
                    }

                    babylonLight.includedOnlyMeshesIds = incllist.ToArray();
                    babylonLight.excludedMeshesIds     = excllist.ToArray();
                }
            }
            catch (Exception e)
            {
                RaiseMessage("Light exclusion not supported", 2);
            }

            // Other fields
            babylonLight.intensity = maxLight.GetIntensity(0, Tools.Forever);


            babylonLight.diffuse  = lightState.AffectDiffuse ? maxLight.GetRGBColor(0, Tools.Forever).ToArray() : new float[] { 0, 0, 0 };
            babylonLight.specular = lightState.AffectDiffuse ? maxLight.GetRGBColor(0, Tools.Forever).ToArray() : new float[] { 0, 0, 0 };


            if (maxLight.UseAtten)
            {
                babylonLight.range = maxLight.GetAtten(0, 3, Tools.Forever);
            }


            // Animations
            var animations = new List <BabylonAnimation>();

            GeneratePositionAnimation(lightNode, animations);

            ExportVector3Animation("direction", animations, key =>
            {
                var localMatrixAnimDir = lightNode.GetLocalTM(key);

                var positionLight = localMatrixAnimDir.Translation;
                var lightTarget   = gameLight.LightTarget;
                if (lightTarget != null)
                {
                    var targetWm       = lightTarget.GetObjectTM(key);
                    var targetPosition = targetWm.Translation;

                    var direction = targetPosition.Subtract(positionLight).Normalize;
                    return(new[] { direction.X, direction.Y, direction.Z });
                }
                else
                {
                    var vDir = Loader.Global.Point3.Create(0, -1, 0);
                    vDir     = localMatrixAnimDir.ExtractMatrix3().VectorTransform(vDir).Normalize;
                    return(new[] { vDir.X, vDir.Y, vDir.Z });
                }
            });

            // Animation temporary stored for gltf but not exported for babylon
            // TODO - Will cause an issue when externalizing the glTF export process
            var extraAnimations = new List <BabylonAnimation>();
            // Do not check if node rotation properties are animated
            GenerateRotationAnimation(lightNode, extraAnimations, true);
            babylonLight.extraAnimations = extraAnimations;

            ExportFloatAnimation("intensity", animations, key => new[] { maxLight.GetIntensity(key, Tools.Forever) });

            ExportColor3Animation("diffuse", animations, key =>
            {
                return(lightState.AffectDiffuse? maxLight.GetRGBColor(key, Tools.Forever).ToArray() : new float[] { 0, 0, 0 });
            });

            babylonLight.animations = animations.ToArray();

            if (lightNode.MaxNode.GetBoolProperty("babylonjs_autoanimate"))
            {
                babylonLight.autoAnimate     = true;
                babylonLight.autoAnimateFrom = (int)lightNode.MaxNode.GetFloatProperty("babylonjs_autoanimate_from");
                babylonLight.autoAnimateTo   = (int)lightNode.MaxNode.GetFloatProperty("babylonjs_autoanimate_to");
                babylonLight.autoAnimateLoop = lightNode.MaxNode.GetBoolProperty("babylonjs_autoanimateloop");
            }

            babylonScene.LightsList.Add(babylonLight);

            return(babylonLight);
        }
        private BabylonAnimation GetDummyAnimation(GLTFNode gltfNode, int startFrame, int endFrame, BabylonScene babylonScene)
        {
            BabylonAnimation dummyAnimation = new BabylonAnimation();

            dummyAnimation.name           = "Dummy";
            dummyAnimation.property       = "scaling";
            dummyAnimation.framePerSecond = babylonScene.TimelineFramesPerSecond;
            dummyAnimation.dataType       = (int)BabylonAnimation.DataType.Vector3;

            BabylonAnimationKey startKey = new BabylonAnimationKey();

            startKey.frame  = startFrame;
            startKey.values = gltfNode.scale;

            BabylonAnimationKey endKey = new BabylonAnimationKey();

            endKey.frame  = endFrame;
            endKey.values = gltfNode.scale;

            dummyAnimation.keys = new BabylonAnimationKey[] { startKey, endKey };

            return(dummyAnimation);
        }
Example #26
0
 public BabylonTexture ExportTexture(MFnDependencyNode textureDependencyNode, BabylonScene babylonScene, bool allowCube = false, bool forceAlpha = false, bool forceSpherical = false, float amount = 1.0f)
 {
     logRankTexture = 2;
     return(_ExportTexture(textureDependencyNode, babylonScene, null, allowCube, forceAlpha, forceSpherical, amount));
 }
        private bool ExportMorphTargetWeightAnimation(BabylonMorphTargetManager babylonMorphTargetManager, GLTF gltf, GLTFNode gltfNode, List <GLTFChannel> channelList, List <GLTFAnimationSampler> samplerList, int startFrame, int endFrame, BabylonScene babylonScene, bool offsetToStartAtFrameZero = true)
        {
            if (exportedMorphTargets.Contains(babylonMorphTargetManager) || !_isBabylonMorphTargetManagerAnimationValid(babylonMorphTargetManager))
            {
                return(false);
            }

            var influencesPerFrame = _getTargetManagerAnimationsData(babylonMorphTargetManager);
            var frames             = new List <int>(influencesPerFrame.Keys);

            var framesInRange = frames.Where(frame => frame >= startFrame && frame <= endFrame).ToList();

            framesInRange.Sort(); // Mandatory to sort otherwise gltf loader of babylon doesn't understand
            if (framesInRange.Count() <= 0)
            {
                return(false);
            }

            logger.RaiseMessage("GLTFExporter.Animation | Export animation of morph target manager with id: " + babylonMorphTargetManager.id, 2);

            // Target
            var gltfTarget = new GLTFChannelTarget
            {
                node = gltfNode.index
            };

            gltfTarget.path = "weights";

            // Buffer
            var buffer = GLTFBufferService.Instance.GetBuffer(gltf);

            // --- Input ---
            var accessorInput = GLTFBufferService.Instance.CreateAccessor(
                gltf,
                GLTFBufferService.Instance.GetBufferViewAnimationFloatScalar(gltf, buffer),
                "accessorAnimationInput",
                GLTFAccessor.ComponentType.FLOAT,
                GLTFAccessor.TypeEnum.SCALAR
                );

            // Populate accessor
            accessorInput.min = new float[] { float.MaxValue };
            accessorInput.max = new float[] { float.MinValue };

            int numKeys = 0;

            foreach (var frame in framesInRange)
            {
                numKeys++;
                float inputValue = frame;
                if (offsetToStartAtFrameZero)
                {
                    inputValue -= startFrame;
                }
                inputValue /= (float)babylonScene.TimelineFramesPerSecond;
                // Store values as bytes
                accessorInput.bytesList.AddRange(BitConverter.GetBytes(inputValue));
                // Update min and max values
                GLTFBufferService.UpdateMinMaxAccessor(accessorInput, inputValue);
            }
            accessorInput.count = numKeys;

            if (accessorInput.count == 0)
            {
                logger.RaiseWarning(String.Format("GLTFExporter.Animation | No frames to export in morph target animation \"weight\" for mesh named \"{0}\". This will cause an error in the output gltf.", babylonMorphTargetManager.sourceMesh.name));
            }

            // --- Output ---
            GLTFAccessor accessorOutput = GLTFBufferService.Instance.CreateAccessor(
                gltf,
                GLTFBufferService.Instance.GetBufferViewAnimationFloatScalar(gltf, buffer),
                "accessorAnimationWeights",
                GLTFAccessor.ComponentType.FLOAT,
                GLTFAccessor.TypeEnum.SCALAR
                );

            // Populate accessor
            foreach (var frame in framesInRange)
            {
                var outputValues = influencesPerFrame[frame];
                // Store values as bytes
                foreach (var outputValue in outputValues)
                {
                    accessorOutput.count++;
                    accessorOutput.bytesList.AddRange(BitConverter.GetBytes(outputValue));
                }
            }

            // Animation sampler
            var gltfAnimationSampler = new GLTFAnimationSampler
            {
                input  = accessorInput.index,
                output = accessorOutput.index
            };

            gltfAnimationSampler.index = samplerList.Count;
            samplerList.Add(gltfAnimationSampler);

            // Channel
            var gltfChannel = new GLTFChannel
            {
                sampler = gltfAnimationSampler.index,
                target  = gltfTarget
            };

            channelList.Add(gltfChannel);

            // Mark this morph target as exported.
            exportedMorphTargets.Add(babylonMorphTargetManager);
            return(true);
        }
Example #28
0
        private BabylonTexture _ExportTexture(MFnDependencyNode materialDependencyNode, string plugName, BabylonScene babylonScene, bool allowCube = false, bool forceAlpha = false, bool updateCoordinatesMode = false, float amount = 1.0f)
        {
            if (!materialDependencyNode.hasAttribute(plugName))
            {
                RaiseError("Unknown attribute " + materialDependencyNode.name + "." + plugName, logRankTexture);
                return(null);
            }
            List <MFnDependencyNode> textureModifiers      = new List <MFnDependencyNode>();
            MFnDependencyNode        textureDependencyNode = getTextureDependencyNode(materialDependencyNode, plugName, textureModifiers);

            return(_ExportTexture(textureDependencyNode, babylonScene, textureModifiers, allowCube, forceAlpha, updateCoordinatesMode, amount));
        }
Example #29
0
        static void DumpCameras(NovaScene scene, BabylonScene babylonScene)
        {
            foreach (NovaCamera camera in scene.Cameras)
            {
                var babylonCamera = new BabylonCamera();
                babylonScene.CamerasList.Add(babylonCamera);

                babylonCamera.name = camera.Name;
                babylonCamera.id = camera.ID.ToString();
                babylonCamera.position = camera.Position.ToArray();
                babylonCamera.rotation = camera.Rotation.ToArray();
                babylonCamera.fov = camera.FOV;
                babylonCamera.minZ = camera.NearClip;
                babylonCamera.maxZ = camera.FarClip;
                babylonCamera.inertia = camera.Inertia;
                babylonCamera.speed = camera.Speed;
                babylonCamera.checkCollisions = camera.CheckCollisions;
                babylonCamera.applyGravity = camera.ApplyGravity;
                babylonCamera.ellipsoid = camera.EllipsoidVector.ToArray();
            }

            if (scene.ActiveCamera != null)
            {
                babylonScene.activeCameraID = scene.ActiveCamera.ID.ToString();
            }
        }
Example #30
0
        void ParseMesh(ModelMesh modelMesh, BabylonScene scene, BabylonSkeleton skeleton)
        {
            var proxyID = ProxyMesh.CreateBabylonMesh(modelMesh.Name, scene);
            int indexName = 0;

            foreach (var part in modelMesh.MeshParts)
            {
                var material = exportedMaterials.First(m => m.Name == part.Effect.GetHashCode().ToString());

                var indices = new ushort[part.PrimitiveCount * 3];
                part.IndexBuffer.GetData(part.StartIndex * 2, indices, 0, indices.Length);

                if (part.VertexBuffer.VertexDeclaration.VertexStride >= PositionNormalTexturedWeights.Stride)
                {
                    var mesh = new Mesh<PositionNormalTexturedWeights>(material);
                    var vertices = new PositionNormalTexturedWeights[part.NumVertices];

                    part.VertexBuffer.GetData(part.VertexOffset * part.VertexBuffer.VertexDeclaration.VertexStride, vertices, 0, vertices.Length, part.VertexBuffer.VertexDeclaration.VertexStride);

                    for (int index = 0; index < vertices.Length; index++)
                    {
                        vertices[index].TextureCoordinates.Y = 1.0f - vertices[index].TextureCoordinates.Y;
                    }

                    mesh.AddPart(indexName.ToString(), vertices.ToList(), indices.Select(i => (int)i).ToList());
                    mesh.CreateBabylonMesh(scene, proxyID, skeleton);
                }
                else
                {
                    var mesh = new Mesh<PositionNormalTextured>(material);
                    var vertices = new PositionNormalTextured[part.NumVertices];
                    part.VertexBuffer.GetData(part.VertexOffset * PositionNormalTextured.Stride, vertices, 0, vertices.Length, PositionNormalTextured.Stride);

                    for (int index = 0; index < vertices.Length; index++)
                    {
                        vertices[index].TextureCoordinates.Y = 1.0f - vertices[index].TextureCoordinates.Y;
                    }

                    mesh.AddPart(indexName.ToString(), vertices.ToList(), indices.Select(i => (int)i).ToList());
                    mesh.CreateBabylonMesh(scene, proxyID, skeleton);
                }

                indexName++;
            }
        }
Example #31
0
        private void DumpParticles(BabylonScene babylonScene)
        {
            if (particleSystemsToExport.Count == 0)
                return;

            babylonScene.particleSystems = new BabylonParticleSystem[particleSystemsToExport.Count];

            var index = 0;
            foreach (var particleSystem in particleSystemsToExport)
            {
                babylonScene.particleSystems[index] = new BabylonParticleSystem
                    {
                        capacity = particleSystem.BufferSize,
                        emitterId = particleSystem.Emitter.ID.ToString(),
                        gravity = particleSystem.Gravity.ToArray(),
                        direction1 = Vector3.TransformNormal(particleSystem.Direction1, particleSystem.Emitter.LocalMatrix).ToArray(),
                        direction2 = Vector3.TransformNormal(particleSystem.Direction2, particleSystem.Emitter.LocalMatrix).ToArray(),
                        minEmitBox = particleSystem.MinEmitBox.ToArray(),
                        maxEmitBox = particleSystem.MaxEmitBox.ToArray(),
                        color1 = particleSystem.Color1.ToArray(),
                        color2 = particleSystem.Color2.ToArray(),
                        colorDead = new RGBAColor(particleSystem.ColorDead.Red, particleSystem.ColorDead.Green, particleSystem.ColorDead.Blue, particleSystem.DeadAlpha).ToArray(),
                        emitRate = particleSystem.EmitRate,
                        updateSpeed = particleSystem.UpdateSpeed,
                        targetStopFrame = particleSystem.TargetStopFrame,
                        minEmitPower = particleSystem.MinEmitPower,
                        maxEmitPower = particleSystem.MaxEmitPower,
                        minLifeTime = particleSystem.MinLifeTime,
                        maxLifeTime = particleSystem.MaxLifeTime,
                        minSize = particleSystem.MinSize,
                        maxSize = particleSystem.MaxSize,
                        minAngularSpeed = particleSystem.MinAngularSpeed,
                        maxAngularSpeed = particleSystem.MaxAngularSpeed,
                        textureName = CopyTexture(particleSystem.Texture, babylonScene),
                        blendMode = (int)particleSystem.BlendType,
                        linkToEmitter = particleSystem.LinkToEmitter
                    };

                Vector4 textureMask = Vector4.Zero;

                switch (particleSystem.TextureUsage)
                {
                    case NovaParticleSystem.ParticleTextureUsages.Alpha:
                        textureMask = new Vector4(0, 0, 0, 1);
                        break;
                    case NovaParticleSystem.ParticleTextureUsages.RGB:
                        textureMask = new Vector4(1, 1, 1, 0);
                        break;
                    case NovaParticleSystem.ParticleTextureUsages.ARGB:
                        textureMask = new Vector4(1, 1, 1, 1);
                        break;
                }

                babylonScene.particleSystems[index].textureMask = textureMask.ToArray();

                index++;
            }
        }
Example #32
0
        void ParseEffect(Effect effect, BabylonScene scene)
        {
            var material = new StandardMaterial(effect.GetHashCode().ToString());

            exportedMaterials.Add(material);

            var basicEffect = effect as BasicEffect;
            var skinnedEffect = effect as SkinnedEffect;

            if (basicEffect != null)
            {
                material.Alpha = basicEffect.Alpha;
                material.Diffuse = basicEffect.DiffuseColor.ToColor3();
                material.Emissive = basicEffect.EmissiveColor.ToColor3();
                material.Specular = basicEffect.SpecularColor.ToColor3();
                material.SpecularPower = basicEffect.SpecularPower;
            }
            else
            {
                material.Alpha = skinnedEffect.Alpha;
                material.Diffuse = skinnedEffect.DiffuseColor.ToColor3();
                material.Emissive = skinnedEffect.EmissiveColor.ToColor3();
                material.Specular = skinnedEffect.SpecularColor.ToColor3();
                material.SpecularPower = skinnedEffect.SpecularPower;
            }

            var texture = basicEffect != null ? basicEffect.Texture : skinnedEffect.Texture;

            if (texture != null)
            {
                var id = texture.GetHashCode().ToString();

                if (!exportedTexturesFilename.ContainsKey(id))
                {
                    var tempPath = Path.GetTempPath();
                    var width = texture.Width;
                    var height = texture.Height;
                    string filename;

                    if (texture.Format != SurfaceFormat.Dxt1)
                    {
                        filename = Path.Combine(tempPath, texturesCount + ".png");
                    }
                    else
                    {
                        filename = Path.Combine(tempPath, texturesCount + ".jpg");
                    }

                    texturesCount++;

                    using (var file = new FileStream(filename, FileMode.Create, FileAccess.Write))
                    {
                        if (texture.Format != SurfaceFormat.Dxt1)
                        {
                            texture.SaveAsPng(file, width, height);
                        }
                        else
                        {
                            texture.SaveAsJpeg(file, width, height);
                        }
                    }

                    exportedTexturesFilename.Add(id, filename);
                }

                material.DiffuseTexture = exportedTexturesFilename[id];
            }

            material.CreateBabylonMaterial(scene);
        }
Example #33
0
        void DumpObject(NovaObject novaObject, BabylonScene babylonScene, NovaScene scene, int startIndex, int endIndex, string nameIndex = "")
        {
            var babylonMesh = new BabylonMesh();
            babylonScene.MeshesList.Add(babylonMesh);

            babylonMesh.name = novaObject.Name + nameIndex;
            babylonMesh.id = novaObject.ID.ToString();
            babylonMesh.materialId = novaObject.Material == null ? "" : novaObject.Material.ID.ToString();
            babylonMesh.parentId = novaObject.ParentEntity == null ? "" : novaObject.ParentEntity.ID.ToString();
            babylonMesh.isEnabled = novaObject.Enabled;
            babylonMesh.isVisible = novaObject.Renderable;
            babylonMesh.visibility = novaObject.Visibility;
            babylonMesh.checkCollisions = novaObject.CheckCollisions;
            babylonMesh.receiveShadows = novaObject.ReceiveShadows;
            babylonMesh.infiniteDistance = novaObject.InfiniteDistance;

            if (novaObject.Billboard)
            {
                babylonMesh.billboardMode |= (novaObject.BillboardX ? 1 : 0);
                babylonMesh.billboardMode |= (novaObject.BillboardY ? 2 : 0);
                babylonMesh.billboardMode |= (novaObject.BillboardZ ? 4 : 0);
            }

            if (novaObject.ParticleSystem != null)
            {
                particleSystemsToExport.Add(novaObject.ParticleSystem);
            }

            // Mirror
            if (novaObject.IsMirror && novaObject.Material != null)
            {
                mirrorsMaterials.Add(novaObject.Material, novaObject);
            }

            // World
            babylonMesh.position = novaObject.Position.ToArray();
            babylonMesh.rotation = novaObject.Rotation.ToArray();
            babylonMesh.localMatrix = (Matrix.Scaling(novaObject.Scaling) * novaObject.LocalMatrix).ToArray();

            // Animations
            var animations = new List<BabylonAnimation>();

            DumpInterpolator("Visibility animation", "visibility", novaObject.VisibilityInterpolator, scene, animations);

            // Position
            if (!DumpInterpolator("Position animation", "position", novaObject.PositionInterpolator, scene, animations))
            {
                DumpInterpolator("PositionX animation", "position.x", novaObject.PositionXInterpolator, scene, animations);
                DumpInterpolator("PositionY animation", "position.y", novaObject.PositionYInterpolator, scene, animations);
                DumpInterpolator("PositionZ animation", "position.z", novaObject.PositionZInterpolator, scene, animations);
            }

            // Rotation
            if (!DumpInterpolator("Rotation animation", "rotationQuaternion", novaObject.RotationInterpolator, scene, animations))
            {
                DumpInterpolator("RotationX animation", "rotation.x", novaObject.RotationXInterpolator, scene,
                    animations, -novaObject.Determinant);
                DumpInterpolator("RotationY animation", "rotation.y", novaObject.RotationYInterpolator, scene,
                    animations, -novaObject.Determinant);
                DumpInterpolator("RotationZ animation", "rotation.z", novaObject.RotationZInterpolator, scene,
                    animations, -novaObject.Determinant);
            }
            else
            {
                babylonMesh.localMatrix = Matrix.Identity.ToArray();
                babylonMesh.scaling = novaObject.Scaling.ToArray();
            }

            // Scaling
            if (!DumpInterpolator("Scaling animation", "scaling", novaObject.ScalingInterpolator, scene, animations))
            {
                DumpInterpolator("ScalingX animation", "scaling.x", novaObject.ScalingXInterpolator, scene, animations);
                DumpInterpolator("ScalingY animation", "scaling.y", novaObject.ScalingYInterpolator, scene, animations);
                DumpInterpolator("ScalingZ animation", "scaling.z", novaObject.ScalingZInterpolator, scene, animations);
            }
            else
            {
                babylonMesh.localMatrix = novaObject.LocalMatrix.ToArray();
                babylonMesh.scaling = novaObject.Scaling.ToArray();
            }

            babylonMesh.animations = animations.ToArray();
            babylonMesh.autoAnimate = novaObject.AutoAnimate;

            if (novaObject.AutoAnimate)
            {
                babylonMesh.autoAnimateFrom = novaObject.AnimationStartKey;
                if (novaObject.AnimationEndKey == -1)
                {
                    babylonMesh.autoAnimateTo = scene.AnimationKeyMax / scene.AnimationKeyStep;
                    babylonMesh.autoAnimateLoop = true;
                }
                else
                {
                    babylonMesh.autoAnimateTo = novaObject.AnimationEndKey;
                }
            }

            // Vertices & faces
            var exportedVerticesCount = DumpObjectGeometry(novaObject, babylonMesh, startIndex, endIndex);

            // Subobjects
            var subMeshes = new List<BabylonSubMesh>();

            if (novaObject.Is32bits)
            {
                var subMesh = new BabylonSubMesh();
                subMesh.materialIndex = 0;
                subMesh.verticesStart = 0;
                subMesh.verticesCount = exportedVerticesCount;
                subMesh.indexStart = 0;
                subMesh.indexCount = babylonMesh.indices.Length;

                subMeshes.Add(subMesh);
            }
            else
            {
                foreach (NovaSubObject subObject in novaObject.SubObjects)
                {
                    var subMesh = new BabylonSubMesh();
                    subMesh.materialIndex = subObject.AttributeRange.AttributeId;
                    subMesh.verticesStart = subObject.AttributeRange.VertexStart;
                    subMesh.verticesCount = subObject.AttributeRange.VertexCount;
                    subMesh.indexStart = subObject.AttributeRange.FaceStart * 3;
                    subMesh.indexCount = subObject.AttributeRange.FaceCount * 3;

                    subMeshes.Add(subMesh);
                }
            }
            babylonMesh.subMeshes = subMeshes.ToArray();

            if (novaObject.Material != null)
            {
                if (!materialsToExport.Contains(novaObject.Material))
                {
                    materialsToExport.Add(novaObject.Material);
                    var multiMat = novaObject.Material as NovaMultiMaterial;

                    if (multiMat != null)
                    {
                        foreach (var mat in multiMat.Materials)
                        {
                            if (!materialsToExport.Contains(mat))
                            {
                                materialsToExport.Add(mat);
                            }
                        }
                    }
                }
            }
        }
        private BabylonTexture ExportBaseColorAlphaTexture(MFnDependencyNode materialDependencyNode, bool useColorMap, bool useOpacityMap, float[] baseColor, float alpha, BabylonScene babylonScene)
        {
            MFnDependencyNode textureDependencyNode = getTextureDependencyNode(materialDependencyNode, "TEX_color_map");

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

            // Prints
            Print(textureDependencyNode, logRankTexture, "Print ExportBaseColorAlphaTexture textureDependencyNode");

            // Retreive texture file path
            string sourcePath = getSourcePathFromFileTexture(textureDependencyNode);

            if (sourcePath == null)
            {
                return(null);
            }
            if (sourcePath == "")
            {
                RaiseError("Texture path is missing.", logRankTexture + 1);
                return(null);
            }

            // Check format
            string extension        = Path.GetExtension(sourcePath);
            var    validImageFormat = 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)), logRankTexture + 1);
                return(null);
            }
            RaiseVerbose("validImageFormat=" + validImageFormat, logRankTexture + 1);

            extension = extension.Substring(1).ToLower(); // remove the dot
            if (useOpacityMap)
            {
                List <string> alphaFormats = new List <string>(new string[] { "png", "tga", "gif" });
                if (!alphaFormats.Contains(extension))
                {
                    validImageFormat = "png";
                }
            }
            else
            {
                List <string> nonAlphaFormats = new List <string>(new string[] { "jpg", "jpeg", "bmp" });
                if (!nonAlphaFormats.Contains(extension))
                {
                    validImageFormat = "jpg";
                }
            }

            var babylonTexture = new BabylonTexture
            {
                name = Path.GetFileNameWithoutExtension(sourcePath) + "." + validImageFormat
            };

            // Level
            babylonTexture.level = 1.0f;

            // UVs
            _exportUV(textureDependencyNode, babylonTexture);

            // Is cube
            _exportIsCube(sourcePath, babylonTexture, false);


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

            if (!File.Exists(sourcePath))
            {
                return(null);
            }

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

            if (CopyTexturesToOutput)
            {
                // Load bitmaps
                var baseColorBitmap = LoadTexture(sourcePath);

                // Retreive dimensions
                int width  = baseColorBitmap.Width;
                int height = baseColorBitmap.Height;

                // 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.GetPixel(x, y);

                        var   __baseColor    = useColorMap ? baseColorAtPixel : _baseColor;
                        var   __alpha        = useOpacityMap ? baseColorAtPixel.A : _alpha;
                        Color baseColorAlpha = Color.FromArgb(__alpha, __baseColor);
                        baseColorAlphaBitmap.SetPixel(x, y, baseColorAlpha);
                    }
                }

                // Write bitmap
                if (isBabylonExported)
                {
                    var absolutePath = Path.Combine(babylonScene.OutputPath, babylonTexture.name);
                    RaiseMessage($"Texture | write image '{babylonTexture.name}'", 2);
                    var imageFormat = useOpacityMap ? System.Drawing.Imaging.ImageFormat.Png : System.Drawing.Imaging.ImageFormat.Jpeg;
                    baseColorAlphaBitmap.Save(absolutePath, imageFormat);
                }
                else
                {
                    // Store created bitmap for further use in gltf export
                    babylonTexture.bitmap = baseColorAlphaBitmap;
                }
            }

            return(babylonTexture);
        }
Example #35
0
        // -------------------------------
        // --- "public" export methods ---
        // -------------------------------

        private BabylonTexture ExportTexture(IStdMat2 stdMat, int index, out BabylonFresnelParameters fresnelParameters, BabylonScene babylonScene, bool allowCube = false, bool forceAlpha = false)
        {
            fresnelParameters = null;

            if (!stdMat.MapEnabled(index))
            {
                return(null);
            }

            var texMap = stdMat.GetSubTexmap(index);

            if (texMap == null)
            {
                RaiseWarning("Texture channel " + index + " activated but no texture found.", 2);
                return(null);
            }

            texMap = _exportFresnelParameters(texMap, out fresnelParameters);

            var amount = stdMat.GetTexmapAmt(index, 0);

            return(ExportTexture(texMap, babylonScene, amount, allowCube, forceAlpha));
        }
Example #36
0
        void DumpLensFlares(BabylonScene babylonScene)
        {
            if (lensFlareSystemToExport.Count == 0)
                return;

            babylonScene.lensFlareSystems = new BabylonLensFlareSystem[lensFlareSystemToExport.Count];

            var index = 0;
            foreach (var lensFlareSystem in lensFlareSystemToExport)
            {
                var flares = new List<BabylonLensFlare>();
                foreach (var flare in lensFlareSystem.Flares)
                {
                    flares.Add(new BabylonLensFlare
                    {
                        color = flare.Color.ToArray(),
                        position = flare.Position,
                        size = flare.Size / 1000.0f,
                        textureName = CopyTexture(flare.Texture, babylonScene)
                    });
                }

                babylonScene.lensFlareSystems[index] = new BabylonLensFlareSystem
                {
                    emitterId = (lensFlareSystem.Tag as NovaLight).ID.ToString(),
                    borderLimit = lensFlareSystem.BorderLimit,
                    flares = flares.ToArray()
                };

                index++;
            }
        }
        private BabylonTexture _ExportTexture(MFnDependencyNode materialDependencyNode, string plugName, BabylonScene babylonScene, bool allowCube = false, bool forceAlpha = false, bool forceSpherical = false, float amount = 1.0f)
        {
            if (!materialDependencyNode.hasAttribute(plugName))
            {
                RaiseError("Unknown attribute " + materialDependencyNode.name + "." + plugName, logRankTexture);
                return(null);
            }

            MFnDependencyNode textureDependencyNode = getTextureDependencyNode(materialDependencyNode, plugName);

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

            Print(textureDependencyNode, logRankTexture, "Print _ExportTexture textureDependencyNode");

            // Retreive texture file path
            string sourcePath = getSourcePathFromFileTexture(textureDependencyNode);

            if (sourcePath == null)
            {
                RaiseError("Texture path is not a valid string.", logRankTexture + 1);
                return(null);
            }
            if (sourcePath == "")
            {
                RaiseError("Texture path is missing.", logRankTexture + 1);
                return(null);
            }

            // Check format
            var validImageFormat = 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)), logRankTexture + 1);
                return(null);
            }
            RaiseVerbose("validImageFormat=" + validImageFormat, logRankTexture + 1);

            var babylonTexture = new BabylonTexture
            {
                name = Path.GetFileNameWithoutExtension(sourcePath) + "." + validImageFormat
            };

            // Level
            babylonTexture.level = amount;

            // Alpha
            babylonTexture.hasAlpha = forceAlpha;
            // When fileHasAlpha = true:
            // - texture's format has alpha (png, tif, tga...)
            // - and at least one pixel has an alpha value < 255
            babylonTexture.getAlphaFromRGB = !textureDependencyNode.findPlug("fileHasAlpha").asBoolProperty;

            // UVs
            _exportUV(textureDependencyNode, babylonTexture, forceSpherical);

            // TODO - Animations

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

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

            return(babylonTexture);
        }
Example #38
0
        void DumpObjects(NovaScene scene, BabylonScene babylonScene)
        {
            int count = 0;
            foreach (NovaObject novaObject in scene.Objects)
            {
                if (novaObject.Is32bits)
                {
                    if (novaObject.SubObjects.Count == 1)
                    {
                        var total = novaObject.VerticesCount;
                        const int step = 32000;
                        var stepsCount = (int)(Math.Floor((float)total / step) + 1);

                        for (var index = 0; index < stepsCount; index++)
                        {
                            var start = index * step;
                            var end = (index + 1) * step;
                            DumpObject(novaObject, babylonScene, scene, start, end, string.Format("#{0}", index));
                        }
                    }
                }
                else
                {
                    DumpObject(novaObject, babylonScene, scene, 0, novaObject.VerticesCount);
                }

                ReportProgressChanged(50 + (count++ * 25) / scene.Objects.Count);
            }
        }
        private BabylonTexture ExportMetallicRoughnessTexture(MFnDependencyNode materialDependencyNode, bool useMetallicMap, bool useRoughnessMap, BabylonScene babylonScene, string materialName)
        {
            MFnDependencyNode metallicTextureDependencyNode  = useMetallicMap ? getTextureDependencyNode(materialDependencyNode, "TEX_metallic_map") : null;
            MFnDependencyNode roughnessTextureDependencyNode = useRoughnessMap ? getTextureDependencyNode(materialDependencyNode, "TEX_roughness_map") : null;

            // Prints
            if (metallicTextureDependencyNode != null)
            {
                Print(metallicTextureDependencyNode, logRankTexture, "Print ExportMetallicRoughnessTexture metallicTextureDependencyNode");
            }
            if (roughnessTextureDependencyNode != null)
            {
                Print(roughnessTextureDependencyNode, logRankTexture, "Print ExportMetallicRoughnessTexture roughnessTextureDependencyNode");
            }

            // Use one as a reference for UVs parameters
            var textureDependencyNode = metallicTextureDependencyNode != null ? metallicTextureDependencyNode : roughnessTextureDependencyNode;

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

            var babylonTexture = new BabylonTexture
            {
                name = materialName + "_metallicRoughness" + ".jpg" // TODO - unsafe name, may conflict with another texture name
            };

            // Level
            babylonTexture.level = 1.0f;

            // No alpha
            babylonTexture.hasAlpha        = false;
            babylonTexture.getAlphaFromRGB = false;

            // UVs
            _exportUV(textureDependencyNode, babylonTexture);

            // Is cube
            string sourcePath = getSourcePathFromFileTexture(textureDependencyNode);

            if (sourcePath == null)
            {
                return(null);
            }
            if (sourcePath == "")
            {
                RaiseError("Texture path is missing.", logRankTexture + 1);
                return(null);
            }
            _exportIsCube(sourcePath, babylonTexture, false);


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

            if (CopyTexturesToOutput)
            {
                // Load bitmaps
                var metallicBitmap  = LoadTexture(metallicTextureDependencyNode);
                var roughnessBitmap = LoadTexture(roughnessTextureDependencyNode);

                // Retreive dimensions
                int width              = 0;
                int height             = 0;
                var haveSameDimensions = _getMinimalBitmapDimensions(out width, out height, metallicBitmap, roughnessBitmap);
                if (!haveSameDimensions)
                {
                    RaiseError("Metallic and roughness maps should have same dimensions", 2);
                }

                // Create metallic+roughness map
                Bitmap metallicRoughnessBitmap = new Bitmap(width, height);
                for (int x = 0; x < width; x++)
                {
                    for (int y = 0; y < height; y++)
                    {
                        var _metallic = metallicBitmap != null?metallicBitmap.GetPixel(x, y).B : 255.0f;

                        var _roughness = roughnessBitmap != null?roughnessBitmap.GetPixel(x, y).G : 255.0f;

                        // 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)_roughness,
                            (int)_metallic
                            );
                        metallicRoughnessBitmap.SetPixel(x, y, colorMetallicRoughness);
                    }
                }

                // Write bitmap
                if (isBabylonExported)
                {
                    var absolutePath = Path.Combine(babylonScene.OutputPath, babylonTexture.name);
                    RaiseMessage($"Texture | write image '{babylonTexture.name}'", 2);
                    metallicRoughnessBitmap.Save(absolutePath, System.Drawing.Imaging.ImageFormat.Jpeg);
                }
                else
                {
                    // Store created bitmap for further use in gltf export
                    babylonTexture.bitmap = metallicRoughnessBitmap;
                }
            }

            return(babylonTexture);
        }
Example #40
0
        void DumpCameras(NovaScene scene, BabylonScene babylonScene)
        {
            foreach (NovaCamera camera in scene.Cameras)
            {
                var babylonCamera = new BabylonCamera();
                babylonScene.CamerasList.Add(babylonCamera);

                babylonCamera.name = camera.Name;
                babylonCamera.id = camera.ID.ToString();
                babylonCamera.parentId = camera.ParentEntity == null ? "" : camera.ParentEntity.ID.ToString();
                babylonCamera.lockedTargetId = camera.Target == null ? "" : camera.Target.ID.ToString();
                babylonCamera.position = camera.Position.ToArray();
                babylonCamera.rotation = camera.Rotation.ToArray();
                babylonCamera.fov = camera.FOV;
                babylonCamera.minZ = camera.NearClip;
                babylonCamera.maxZ = camera.FarClip;
                babylonCamera.inertia = camera.Inertia;
                babylonCamera.speed = camera.Speed;
                babylonCamera.checkCollisions = camera.CheckCollisions;
                babylonCamera.applyGravity = camera.ApplyGravity;
                babylonCamera.ellipsoid = camera.EllipsoidVector.ToArray();

                // Animations
                var animations = new List<BabylonAnimation>();

                // Position
                if (!DumpInterpolator("Position animation", "position", camera.PositionInterpolator, scene, animations))
                {
                    DumpInterpolator("PositionX animation", "position.x", camera.PositionXInterpolator, scene, animations);
                    DumpInterpolator("PositionY animation", "position.y", camera.PositionYInterpolator, scene, animations);
                    DumpInterpolator("PositionZ animation", "position.z", camera.PositionZInterpolator, scene, animations);
                }

                babylonCamera.animations = animations.ToArray();
                babylonCamera.autoAnimate = camera.AutoAnimate;

                if (camera.AutoAnimate)
                {
                    babylonCamera.autoAnimateFrom = camera.AnimationStartKey;
                    if (camera.AnimationEndKey == -1)
                    {
                        babylonCamera.autoAnimateTo = scene.AnimationKeyMax / scene.AnimationKeyStep;
                        babylonCamera.autoAnimateLoop = true;
                    }
                    else
                    {
                        babylonCamera.autoAnimateTo = camera.AnimationEndKey;
                    }
                }
            }

            if (scene.ActiveCamera != null)
            {
                babylonScene.activeCameraID = scene.ActiveCamera.ID.ToString();
            }
        }
Example #41
0
        private void ExportMaterial(IMtl materialNode, BabylonScene babylonScene)
        {
            var name = materialNode.Name;
            var id   = materialNode.GetGuid().ToString();

            RaiseMessage(name, 1);

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

                var guids = new List <string>();

                for (var index = 0; index < materialNode.NumSubMtls; index++)
                {
                    var subMat = materialNode.GetSubMtl(index);

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

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

                babylonMultimaterial.materials = guids.ToArray();

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


            var babylonMaterial = new BabylonMaterial();

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



            babylonMaterial.ambient       = materialNode.GetAmbient(0, false).ToArray();
            babylonMaterial.diffuse       = materialNode.GetDiffuse(0, false).ToArray();
            babylonMaterial.specular      = materialNode.GetSpecular(0, false).Scale(materialNode.GetShinStr(0, false));
            babylonMaterial.specularPower = materialNode.GetShininess(0, false) * 256;

            babylonMaterial.emissive = materialNode.GetSelfIllumColorOn(0, false) ? materialNode.GetSelfIllumColor(0, false).ToArray() : materialNode.GetDiffuse(0, false).Scale(materialNode.GetSelfIllum(0, false));
            babylonMaterial.alpha    = 1.0f - materialNode.GetXParency(0, false);

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

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

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

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

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

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

            babylonScene.MaterialsList.Add(babylonMaterial);
        }
Example #42
0
        private IList <BabylonAnimationGroup> ExportAnimationGroups(BabylonScene babylonScene)
        {
            IList <BabylonAnimationGroup> animationGroups = new List <BabylonAnimationGroup>();

            // Retrieve and parse animation group data
            AnimationGroupList animationList = AnimationGroupList.InitAnimationGroups(logger);

            foreach (AnimationGroup animGroup in animationList)
            {
                logger?.RaiseMessage("Exporter.animationGroups | " + animGroup.Name, 1);
                BabylonAnimationGroup animationGroup = new BabylonAnimationGroup
                {
                    name               = animGroup.Name,
                    from               = animGroup.FrameStart,
                    to                 = animGroup.FrameEnd,
                    keepNonAnimated    = animGroup.KeepNonAnimated,
                    targetedAnimations = new List <BabylonTargetedAnimation>()
                };

                // add animations of each nodes contained in the animGroup
                foreach (Guid guid in animGroup.NodeGuids)
                {
                    IINode maxNode = Tools.GetINodeByGuid(guid);

                    // node could have been deleted, silently ignore it
                    if (maxNode == null)
                    {
                        continue;
                    }

                    if (exportParameters.exportAsSubmodel && !maxNode.Selected)
                    {
                        continue;
                    }


                    // Helpers can be exported as dummies and as bones
                    string nodeId = maxNode.GetGuid().ToString();
                    string boneId = isGltfExported?maxNode.GetGuid().ToString(): maxNode.GetGuid().ToString() + "-bone";   // the suffix "-bone" is added in babylon export format to assure the uniqueness of IDs

                    // Node
                    BabylonNode node = null;
                    babylonScene.NodeMap.TryGetValue(nodeId, out node);
                    if (node != null)
                    {
                        if (node.animations != null && node.animations.Length != 0)
                        {
                            IList <BabylonAnimation> animations = GetSubAnimations(node, animationGroup.from, animationGroup.to);

                            if (!animGroup.KeepStaticAnimation)
                            {
                                RemoveStaticAnimations(ref animations);
                            }

                            foreach (BabylonAnimation animation in animations)
                            {
                                BabylonTargetedAnimation targetedAnimation = new BabylonTargetedAnimation
                                {
                                    animation = animation,
                                    targetId  = nodeId
                                };

                                animationGroup.targetedAnimations.Add(targetedAnimation);
                            }
                        }
                    }

                    // bone
                    BabylonBone bone  = null;
                    int         index = 0;
                    while (index < babylonScene.SkeletonsList.Count && bone == null)
                    {
                        BabylonSkeleton skel = babylonScene.SkeletonsList[index];
                        bone = skel.bones.FirstOrDefault(b => b.id == boneId);
                        index++;
                    }

                    if (bone != null)
                    {
                        if (bone.animation != null)
                        {
                            IList <BabylonAnimation> animations = GetSubAnimations(bone, animationGroup.from, animationGroup.to);
                            foreach (BabylonAnimation animation in animations)
                            {
                                BabylonTargetedAnimation targetedAnimation = new BabylonTargetedAnimation
                                {
                                    animation = animation,
                                    targetId  = boneId
                                };

                                animationGroup.targetedAnimations.Add(targetedAnimation);
                            }
                        }
                    }
                }

                // add animations of each nodes contained in the animGroup
                foreach (Guid guid in animGroup.MaterialGuids)
                {
                    IMtl maxMtl = Tools.GetIMtlByGuid(guid);

                    // mat could have been deleted, silently ignore it
                    if (maxMtl == null)
                    {
                        continue;
                    }

                    string matId = maxMtl.GetGuid().ToString();

                    // Material
                    BabylonMaterial material = null;
                    material = babylonScene.MaterialsList.FirstOrDefault(x => x.id == matId);
                    if (material != null)
                    {
                        if (material.animations != null && material.animations.Length != 0)
                        {
                            IList <BabylonAnimation> animations = GetSubAnimations(material, animationGroup.from, animationGroup.to);
                            foreach (BabylonAnimation animation in animations)
                            {
                                BabylonTargetedAnimation targetedAnimation = new BabylonTargetedAnimation
                                {
                                    animation = animation,
                                    targetId  = matId
                                };

                                animationGroup.targetedAnimations.Add(targetedAnimation);
                            }
                        }
                    }
                }

                if (animationGroup.targetedAnimations.Count > 0)
                {
                    animationGroups.Add(animationGroup);
                }
            }

            return(animationGroups);
        }
Example #43
0
        private List <BabylonNode> getDescendants(BabylonNode babylonNode, BabylonScene babylonScene)
        {
            List <BabylonNode> babylonNodes = getNodes(babylonScene);

            return(babylonNodes.FindAll(node => node.parentId == babylonNode.id));
        }