示例#1
0
        // Utility method: Get the first item of the selection list
        private static MDagPath GetFirstSelected()
        {
            var selected = MGlobal.activeSelectionList;
            var it       = new MItSelectionList(selected);

            if (it.isDone)
            {
                return(null);
            }
            var path = new MDagPath();

            it.getDagPath(path);
            return(path);
        }
示例#2
0
        public MObject GetFirstSelectedObject()
        {
            var selected = MGlobal.activeSelectionList;
            var it       = new MItSelectionList(selected);

            if (it.isDone)
            {
                return(null);
            }
            var     path = new MDagPath();
            MObject mesh = new MObject();

            it.getDagPath(path, mesh);
            return(mesh);
        }
        // Switching to 3D preview
        private void TabControl_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            e.Handled = true;
            if (TabControl1.SelectedIndex == 1)                 // If the result view was selected
            {
                if (!ResultGrid.HasItems)
                {
                    SearchButton_Click(null, null);
                }
                return;
            }
            if (TabControl1.SelectedIndex == 2)                 // If the 3D view was selected
            {
                ResetUpAxis();
                ResetCamera();
                ResetLights();

                // Reset the model & transform(s)
                this.model.Children.Clear();
                //var selected = GetFirstSelected ();
                //// The reason why there might not be a selection is if some tool isn't closed
                //// and prevent the previous selection command from going through
                //if ( selected != null ) {
                //    // If it's a mesh, display it
                //    if ( selected.node.apiTypeStr == "kMesh" ) {
                //        var mesh = new MFnMesh (selected);
                //        // This can take some time, so change the cursor
                //        using ( new CursorSwitcher (null) ) {
                //            model.Children.Add (MakeVisualModel (mesh));
                //        }
                //    }
                //}
                using (new CursorSwitcher(null)) {
                    _singleMeshPreviewed = MGlobal.activeSelectionList.length == 1;
                    MItSelectionList it = new MItSelectionList(MGlobal.activeSelectionList);
                    for ( ; !it.isDone; it.next())
                    {
                        MDagPath path = new MDagPath();
                        it.getDagPath(path);
                        if (path.node.apiTypeStr == "kMesh")
                        {
                            model.Children.Add(MakeVisualModel(path));
                        }
                    }
                }
                return;
            }
        }
示例#4
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)
        {
            // Chekc 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;
            }

            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;

            // 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);

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

            // 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);
                }
            }

            // 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);
        }
 // Utility method
 // Get the first item of the selection list
 private static MDagPath GetFirstSelected()
 {
     var selected = MGlobal.activeSelectionList;
     var it = new MItSelectionList(selected);
     if (it.isDone) return null;
     var path = new MDagPath();
     it.getDagPath(path);
     return path;
 }
示例#6
0
        /// <summary>
        /// Export to file
        /// </summary>
        /// <param name="outputDirectory">The directory to store the generated files</param>
        /// <param name="outputFileName">The filename to use for the generated files</param>
        /// <param name="outputFormat">The format to use for the generated files</param>
        /// <param name="generateManifest">Specifies if a manifest file should be generated</param>
        /// <param name="onlySelected">Specifies if only the selected objects should be exported</param>
        /// <param name="autoSaveMayaFile">Specifies if the Maya scene should be auto-saved</param>
        /// <param name="exportHiddenObjects">Specifies if hidden objects should be exported</param>
        /// <param name="copyTexturesToOutput">Specifies if textures should be copied to the output directory</param>
        /// <param name="optimizeVertices">Specifies if vertices should be optimized on export</param>
        /// <param name="exportTangents">Specifies if tangents should be exported</param>
        /// <param name="scaleFactor">Scales the scene by this factor</param>
        /// <param name="exportSkin">Specifies if skins should be exported</param>
        /// <param name="quality">The texture quality</param>
        /// <param name="dracoCompression">Specifies if draco compression should be used</param>
        /// <param name="exportMorphNormal">Specifies if normals should be exported for morph targets</param>
        /// <param name="exportMorphTangent">Specifies if tangents should be exported for morph targets</param>
        /// <param name="exportKHRLightsPunctual">Specifies if the KHR_lights_punctual extension should be enabled</param>
        /// <param name="exportKHRTextureTransform">Specifies if the KHR_texture_transform extension should be enabled</param>
        /// <param name="bakeAnimationFrames">Specifies if animations should be exporting keyframes directly or should manually bake out animations frame by frame</param>
        public void Export(ExportParameters exportParameters)
        {
            this.exportParameters = exportParameters;

            // Check if the animation is running
            MGlobal.executeCommand("play -q - state", out int isPlayed);
            if (isPlayed == 1)
            {
                RaiseError("Stop the animation before exporting.");
                return;
            }

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

            ReportProgressChanged(progression);

            // Store export options
            this.isBabylonExported = exportParameters.outputFormat == "babylon" || exportParameters.outputFormat == "binary babylon";

            var outputBabylonDirectory = Path.GetDirectoryName(exportParameters.outputPath);

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

            var watch = new Stopwatch();

            watch.Start();


            var babylonScene = new BabylonScene(outputBabylonDirectory);

            // Save scene
            if (exportParameters.autoSaveSceneFile)
            {
                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
            var outputFileName = Path.ChangeExtension(Path.GetFileName(exportParameters.outputPath), "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();

            babylonScene.TimelineStartFrame      = Loader.GetMinTime();
            babylonScene.TimelineEndFrame        = Loader.GetMaxTime();
            babylonScene.TimelineFramesPerSecond = Loader.GetFPS();

            // 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;

                try
                {
                    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;
                    }
                }
                catch (Exception e)
                {
                    this.RaiseWarning(String.Format("Exception raised during export. Node will be exported as dummy node. \r\nMessage: \r\n{0} \r\n{1}", e.Message, e.InnerException), 2);
                }

                // 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 (!exportParameters.pbrNoLight && 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);
            }

            var sceneScaleFactor = exportParameters.scaleFactor;

            if (exportParameters.scaleFactor != 1.0f)
            {
                RaiseMessage(String.Format("A root node is added to globally scale the scene by {0}", sceneScaleFactor), 1);

                // Create root node for scaling
                BabylonMesh rootNode = new BabylonMesh {
                    name = "root", id = Tools.GenerateUUID()
                };
                rootNode.isDummy = true;
                float rootNodeScale = sceneScaleFactor;
                rootNode.scaling = new float[3] {
                    rootNodeScale, rootNodeScale, rootNodeScale
                };

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

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

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

            // --------------------
            // ----- Materials ----
            // --------------------
            RaiseMessage("Exporting materials");
            GenerateMaterialDuplicationDatas(babylonScene);
            foreach (var mat in referencedMaterials)
            {
                ExportMaterial(mat, babylonScene, exportParameters.pbrFull);
                CheckCancelled();
            }
            foreach (var mat in multiMaterials)
            {
                ExportMultiMaterial(mat.Key, mat.Value, babylonScene, exportParameters.pbrFull);
                CheckCancelled();
            }
            UpdateMeshesMaterialId(babylonScene);
            RaiseMessage(string.Format("Total: {0}", babylonScene.MaterialsList.Count + babylonScene.MultiMaterialsList.Count), Color.Gray, 1);


            // Export skeletons
            if (exportParameters.exportSkins && 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 groups -----
            // ----------------------------
            RaiseMessage("Export animation groups");
            // add animation groups to the scene
            babylonScene.animationGroups = ExportAnimationGroups(babylonScene);


            if (isBabylonExported)
            {
                // if we are exporting to .Babylon then remove then remove animations from nodes if there are animation groups.
                if (babylonScene.animationGroups.Count > 0)
                {
                    // 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;
                        }
                    }
                }

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

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

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

            // Output
            babylonScene.Prepare(false, false);

            if (isBabylonExported)
            {
                Write(babylonScene, outputBabylonDirectory, outputFileName, exportParameters.outputFormat, exportParameters.generateManifest);
            }

            ReportProgressChanged(100);

            // Export glTF
            if (exportParameters.outputFormat == "gltf" || exportParameters.outputFormat == "glb")
            {
                bool generateBinary = exportParameters.outputFormat == "glb";

                GLTFExporter gltfExporter = new GLTFExporter();
                gltfExporter.ExportGltf(this.exportParameters, babylonScene, outputBabylonDirectory, outputFileName, generateBinary, this);
            }

            watch.Stop();
            RaiseMessage(string.Format("Export done in {0:0.00}s", watch.ElapsedMilliseconds / 1000.0), Color.Blue);
        }
示例#7
0
        public static StaticObject Create()
        {
            MDagPath         meshDagPath       = new MDagPath();
            MItSelectionList selectionIterator = MayaHelper.GetActiveSelectionListIterator(MFn.Type.kMesh);

            selectionIterator.getDagPath(meshDagPath);
            MFnMesh mesh = new MFnMesh(meshDagPath);

            selectionIterator.next();
            if (!selectionIterator.isDone)
            {
                MGlobal.displayError("StaticObject:Create - More than 1 mesh is selected");
                throw new Exception("StaticObject:Create - More than 1 mesh is selected");
            }

            if (!mesh.IsTriangulated())
            {
                MGlobal.displayError("StaticObject:Create - Mesh isn't triangulated");
                throw new Exception("StaticObject:Create - Mesh isn't triangulated");
            }
            if (mesh.ContainsHoles())
            {
                MGlobal.displayError("StaticObject:Create - Mesh Contains holes");
                throw new Exception("StaticObject:Create - Mesh Contains holes");
            }

            MayaMeshData             meshData    = mesh.GetMeshData();
            Dictionary <int, string> shaderNames = new Dictionary <int, string>();
            List <StaticObjectFace>  faces       = new List <StaticObjectFace>();

            //Build Shader Name map
            for (int i = 0; i < meshData.ShaderIndices.Count; i++)
            {
                int shaderIndex = meshData.ShaderIndices[i];

                if (!shaderNames.ContainsKey(shaderIndex))
                {
                    MPlug      shaderPlug = new MFnDependencyNode(meshData.Shaders[shaderIndex]).findPlug("surfaceShader");
                    MPlugArray plugArray  = new MPlugArray();

                    shaderPlug.connectedTo(plugArray, true, false);

                    MFnDependencyNode material = new MFnDependencyNode(shaderPlug[0].node);

                    shaderNames.Add(shaderIndex, material.name);
                }
            }

            //Construct faces
            int currentIndex = 0;

            for (int polygonIndex = 0; polygonIndex < mesh.numPolygons; polygonIndex++)
            {
                int    shaderIndex = meshData.ShaderIndices[polygonIndex];
                uint[] faceIndices =
                {
                    (uint)meshData.TriangleVertices[currentIndex],
                    (uint)meshData.TriangleVertices[currentIndex + 1],
                    (uint)meshData.TriangleVertices[currentIndex + 2]
                };
                Vector2[] uvs =
                {
                    new Vector2(meshData.UArray[currentIndex],         1 - meshData.VArray[currentIndex]),
                    new Vector2(meshData.UArray[currentIndex + 1], 1 - meshData.VArray[currentIndex + 1]),
                    new Vector2(meshData.UArray[currentIndex + 2], 1 - meshData.VArray[currentIndex + 2])
                };


                faces.Add(new StaticObjectFace(faceIndices, shaderNames[shaderIndex], uvs));
                currentIndex += 3;
            }

            return(new StaticObject(CreateSubmeshes(meshData.VertexArray.ToVector3List(), new List <ColorRGBA4B>(), faces)));
        }
        public void Create(SKLFile skl)
        {
            MSelectionList   currentSelection         = MGlobal.activeSelectionList;
            MItSelectionList currentSelectionIterator = new MItSelectionList(currentSelection, MFn.Type.kMesh);
            MDagPath         meshDagPath = new MDagPath();

            if (currentSelectionIterator.isDone)
            {
                MGlobal.displayError("SKNFile:Create - No mesh selected!");
                throw new Exception("SKNFile:Create - No mesh selected!");
            }
            else
            {
                currentSelectionIterator.getDagPath(meshDagPath);
                currentSelectionIterator.next();

                if (!currentSelectionIterator.isDone)
                {
                    MGlobal.displayError("SKNFile:Create - More than one mesh selected!");
                    throw new Exception("SKNFile:Create - More than one mesh selected!");
                }
            }

            MFnMesh mesh = new MFnMesh(meshDagPath);

            //Find Skin Cluster
            MPlug      inMeshPlug        = mesh.findPlug("inMesh");
            MPlugArray inMeshConnections = new MPlugArray();

            inMeshPlug.connectedTo(inMeshConnections, true, false);
            if (inMeshConnections.length == 0)
            {
                MGlobal.displayError("SKNFile:Create - Failed to find Skin Cluster!");
                throw new Exception("SKNFile:Create - Failed to find Skin Cluster!");
            }

            MPlug          outputGeometryPlug = inMeshConnections[0];
            MFnSkinCluster skinCluster        = new MFnSkinCluster(outputGeometryPlug.node);
            MDagPathArray  influenceDagPaths  = new MDagPathArray();
            uint           influenceCount     = skinCluster.influenceObjects(influenceDagPaths);

            MGlobal.displayInfo("SKNFile:Create - Influence Count: " + influenceCount);

            //Get SKL Influence Indices
            MIntArray sklInfluenceIndices = new MIntArray(influenceCount);

            for (int i = 0; i < influenceCount; i++)
            {
                MDagPath jointDagPath = influenceDagPaths[i];

                MGlobal.displayInfo(jointDagPath.fullPathName);

                //Loop through Joint DAG Paths, if we find a math for the influence, write the index
                for (int j = 0; j < skl.JointDagPaths.Count; j++)
                {
                    if (jointDagPath.equalEqual(skl.JointDagPaths[j]))
                    {
                        MGlobal.displayInfo("Found coresponding DAG path");
                        sklInfluenceIndices[i] = j;
                        break;
                    }
                }
            }

            //Add Influence indices to SKL File
            MIntArray maskInfluenceIndex = new MIntArray(influenceCount);

            for (int i = 0; i < influenceCount; i++)
            {
                maskInfluenceIndex[i] = i;
                skl.Influences.Add((short)sklInfluenceIndices[i]);
            }

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

            mesh.getConnectedShaders(meshDagPath.isInstanced ? meshDagPath.instanceNumber : 0, shaders, polygonShaderIndices);

            uint shaderCount = shaders.length;

            if (shaderCount > 32) //iirc 32 is the limit of how many submeshes there can be for an SKN file
            {
                MGlobal.displayError("SKNFile:Create - You've exceeded the maximum limit of 32 shaders");
                throw new Exception("SKNFile:Create - You've exceeded the maximum limit of 32 shaders");
            }

            MIntArray vertexShaders = new MIntArray();

            ValidateMeshTopology(mesh, meshDagPath, polygonShaderIndices, ref vertexShaders, shaderCount);

            //Get Weights
            MFnSingleIndexedComponent vertexIndexedComponent = new MFnSingleIndexedComponent();
            MObject   vertexComponent    = vertexIndexedComponent.create(MFn.Type.kMeshVertComponent);
            MIntArray groupVertexIndices = new MIntArray((uint)mesh.numVertices);

            for (int i = 0; i < mesh.numVertices; i++)
            {
                groupVertexIndices[i] = i;
            }
            vertexIndexedComponent.addElements(groupVertexIndices);

            MDoubleArray weights = new MDoubleArray();
            uint         weightsInfluenceCount = 0;

            skinCluster.getWeights(meshDagPath, vertexComponent, weights, ref weightsInfluenceCount);

            //Check if vertices don't have more than 4 influences and normalize weights
            for (int i = 0; i < mesh.numVertices; i++)
            {
                int    vertexInfluenceCount = 0;
                double weightSum            = 0;
                for (int j = 0; j < weightsInfluenceCount; j++)
                {
                    double weight = weights[(int)(i * weightsInfluenceCount) + j];
                    if (weight != 0)
                    {
                        vertexInfluenceCount++;
                        weightSum += weight;
                    }
                }

                if (vertexInfluenceCount > 4)
                {
                    MGlobal.displayError("SKNFile:Create - Mesh contains a vertex with more than 4 influences");
                    throw new Exception("SKNFile:Create - Mesh contains a vertex with more than 4 influences");
                }

                //Normalize weights
                for (int j = 0; j < weightsInfluenceCount; j++)
                {
                    weights[(int)(i * influenceCount) + j] /= weightSum;
                }
            }

            List <MIntArray>         shaderVertexIndices = new List <MIntArray>();
            List <List <SKNVertex> > shaderVertices      = new List <List <SKNVertex> >();
            List <MIntArray>         shaderIndices       = new List <MIntArray>();

            for (int i = 0; i < shaderCount; i++)
            {
                shaderVertexIndices.Add(new MIntArray());
                shaderVertices.Add(new List <SKNVertex>());
                shaderIndices.Add(new MIntArray());
            }

            MItMeshVertex meshVertexIterator = new MItMeshVertex(meshDagPath);

            for (meshVertexIterator.reset(); !meshVertexIterator.isDone; meshVertexIterator.next())
            {
                int index  = meshVertexIterator.index();
                int shader = vertexShaders[index];
                if (shader == -1)
                {
                    MGlobal.displayWarning("SKNFile:Create - Mesh contains a vertex with no shader");
                    continue;
                }

                MPoint       pointPosition = meshVertexIterator.position(MSpace.Space.kWorld);
                Vector3      position      = new Vector3((float)pointPosition.x, (float)pointPosition.y, (float)pointPosition.z);
                MVectorArray normals       = new MVectorArray();
                MIntArray    uvIndices     = new MIntArray();
                Vector3      normal        = new Vector3();
                byte[]       weightIndices = new byte[4];
                float[]      vertexWeights = new float[4];

                meshVertexIterator.getNormals(normals);

                //Normalize normals
                for (int i = 0; i < normals.length; i++)
                {
                    normal.X += (float)normals[i].x;
                    normal.Y += (float)normals[i].y;
                    normal.Z += (float)normals[i].z;
                }

                normal.X /= normals.length;
                normal.Y /= normals.length;
                normal.Z /= normals.length;

                //Get Weight Influences and Weights
                int weightsFound = 0;
                for (int j = 0; j < weightsInfluenceCount && weightsFound < 4; j++)
                {
                    double weight = weights[(int)(index * weightsInfluenceCount) + j];

                    if (weight != 0)
                    {
                        weightIndices[weightsFound] = (byte)maskInfluenceIndex[j];
                        vertexWeights[weightsFound] = (float)weight;
                        weightsFound++;
                    }
                }

                //Get unique UVs
                meshVertexIterator.getUVIndices(uvIndices);
                if (uvIndices.length != 0)
                {
                    List <int> seen = new List <int>();
                    for (int j = 0; j < uvIndices.length; j++)
                    {
                        int uvIndex = uvIndices[j];
                        if (!seen.Contains(uvIndex))
                        {
                            seen.Add(uvIndex);

                            float u = 0;
                            float v = 0;
                            mesh.getUV(uvIndex, ref u, ref v);

                            SKNVertex vertex = new SKNVertex(position, weightIndices, vertexWeights, normal, new Vector2(u, 1 - v));
                            vertex.UVIndex = uvIndex;

                            shaderVertices[shader].Add(vertex);
                            shaderVertexIndices[shader].append(index);
                        }
                    }
                }
                else
                {
                    MGlobal.displayError("SKNFile:Create - Mesh contains a vertex with no UVs");
                    throw new Exception("SKNFile:Create - Mesh contains a vertex with no UVs");
                }
            }

            //Convert from Maya indices to data indices
            int       currentIndex = 0;
            MIntArray dataIndices  = new MIntArray((uint)mesh.numVertices, -1);

            for (int i = 0; i < shaderCount; i++)
            {
                for (int j = 0; j < shaderVertexIndices[i].length; j++)
                {
                    int index = shaderVertexIndices[i][j];
                    if (dataIndices[index] == -1)
                    {
                        dataIndices[index]             = currentIndex;
                        shaderVertices[i][j].DataIndex = currentIndex;
                    }
                    else
                    {
                        shaderVertices[i][j].DataIndex = dataIndices[index];
                    }

                    currentIndex++;
                }

                this.Vertices.AddRange(shaderVertices[i]);
            }

            MItMeshPolygon polygonIterator = new MItMeshPolygon(meshDagPath);

            for (polygonIterator.reset(); !polygonIterator.isDone; polygonIterator.next())
            {
                int polygonIndex = (int)polygonIterator.index();
                int shaderIndex  = polygonShaderIndices[polygonIndex];

                MIntArray   indices = new MIntArray();
                MPointArray points  = new MPointArray();
                polygonIterator.getTriangles(points, indices);

                if (polygonIterator.hasUVsProperty)
                {
                    MIntArray vertices   = new MIntArray();
                    MIntArray newIndices = new MIntArray(indices.length, -1);
                    polygonIterator.getVertices(vertices);

                    for (int i = 0; i < vertices.length; i++)
                    {
                        int dataIndex = dataIndices[vertices[i]];
                        int uvIndex;
                        polygonIterator.getUVIndex(i, out uvIndex);

                        if (dataIndex == -1 || dataIndex >= this.Vertices.Count)
                        {
                            MGlobal.displayError("SKNFIle:Create - Data Index outside of range");
                            throw new Exception("SKNFIle:Create - Data Index outside of range");
                        }

                        for (int j = dataIndex; j < this.Vertices.Count; j++)
                        {
                            if (this.Vertices[j].DataIndex != dataIndex)
                            {
                                MGlobal.displayError("SKNFIle:Create - Can't find corresponding face vertex in data");
                                throw new Exception("SKNFIle:Create - Can't find corresponding face vertex in data");
                            }
                            else if (this.Vertices[j].UVIndex == uvIndex)
                            {
                                for (int k = 0; k < indices.length; k++)
                                {
                                    if (indices[k] == vertices[i])
                                    {
                                        newIndices[k] = j;
                                    }
                                }

                                break;
                            }
                        }
                    }

                    for (int i = 0; i < newIndices.length; i++)
                    {
                        shaderIndices[shaderIndex].append(newIndices[i]);
                    }
                }
                else
                {
                    for (int i = 0; i < indices.length; i++)
                    {
                        shaderIndices[shaderIndex].append(dataIndices[indices[i]]);
                    }
                }
            }

            uint startIndex  = 0;
            uint startVertex = 0;

            for (int i = 0; i < shaderCount; i++)
            {
                MPlug      shaderPlug = new MFnDependencyNode(shaders[i]).findPlug("surfaceShader");
                MPlugArray plugArray  = new MPlugArray();
                shaderPlug.connectedTo(plugArray, true, false);

                string name        = new MFnDependencyNode(plugArray[0].node).name;
                uint   indexCount  = shaderIndices[i].length;
                uint   vertexCount = shaderVertexIndices[i].length;

                //Copy indices to SKLFile
                for (int j = 0; j < indexCount; j++)
                {
                    this.Indices.Add((ushort)shaderIndices[i][j]);
                }

                this.Submeshes.Add(new SKNSubmesh(name, startVertex, vertexCount, startIndex, indexCount));

                startIndex  += indexCount;
                startVertex += vertexCount;
            }

            MGlobal.displayInfo("SKNFile:Create - Created SKN File");
        }
示例#9
0
        public int[] SetFromSelection(MSelectionList selected = null)
        {
            selectedIndicesList.Clear();
            if (selected == null)
            {
                //
                selected = BasicFunc.GetSelectedList();
            }

            //List<MVector> positions = new List<MVector>();
            MItSelectionList it_selectionList = new MItSelectionList(selected);

            for (; !it_selectionList.isDone; it_selectionList.next())
            {
                MObject  component = new MObject();
                MDagPath item      = new MDagPath();
                it_selectionList.getDagPath(item, component);

                List <int>   selectedIndcies = new List <int>();
                Action <int> xx = (indice) => { selectedIndcies.Add(indice); };

                switch (selectType)
                {
                case SelectType.Edge:
                {
                    MItMeshEdge it_edges = new MItMeshEdge(item, component);
                    for (; !it_edges.isDone; it_edges.next())
                    {
                        selectedIndcies.Add(it_edges.index(0));
                        selectedIndcies.Add(it_edges.index(1));
                    }
                    break;
                }

                case SelectType.Face:
                {
                    MItMeshPolygon it_poly = new MItMeshPolygon(item, component);

                    for (; !it_poly.isDone; it_poly.next())
                    {
                        selectedIndcies.Add((int)it_poly.index());
                    }

                    break;
                }

                case SelectType.Vert:
                {
                    MItMeshVertex it_verts = new MItMeshVertex(item, component);

                    for (; !it_verts.isDone; it_verts.next())
                    {
                        selectedIndcies.Add(it_verts.index());
                    }

                    break;
                }
                }

                selectedIndicesList.Add(selectedIndcies.ToArray());
            }
            int[] resultCount = new int[selectedIndicesList.Count];
            for (int i = 0; i < resultCount.Length; i++)
            {
                resultCount[i] = selectedIndicesList[i].Length;
            }
            return(resultCount);
        }
示例#10
0
 public MObject GetFirstSelectedObject()
 {
     var selected = MGlobal.activeSelectionList;
     var it = new MItSelectionList(selected);
     if (it.isDone) return null;
     var path = new MDagPath();
     MObject mesh=new MObject();
     it.getDagPath(path, mesh);
     return mesh;
 }
示例#11
0
       public void GetVerticeSelected()
       { 
           var selected = MGlobal.activeSelectionList;
           var it = new MItSelectionList(selected,MFn.Type.kMeshVertComponent);

           MObject vertice=new MObject();
           for(; !it.isDone; it.next())
		   {
             
                var path = new MDagPath();
                it.getDagPath(path,vertice);
                MGlobal.displayInfo(path.fullPathName);

                if (!vertice.isNull)
                {

                    MItMeshVertex itvertex = new MItMeshVertex(path, vertice);

                    for (; !itvertex.isDone; itvertex.next())
                    {
                           int index=  itvertex.index();

                           MGlobal.displayInfo(index.ToString()+"\n");
                    }

                } 

           }
           
       }
示例#12
0
        public void UpdateMeshSelection(TriMesh mesh)
        {
            var selected = MGlobal.activeSelectionList;
            var it = new MItSelectionList(selected, MFn.Type.kMeshVertComponent);

            MObject vertice = new MObject();
            for (; !it.isDone; it.next())
            {

                var path = new MDagPath();
                it.getDagPath(path, vertice);
                MGlobal.displayInfo(path.fullPathName);

                if (!vertice.isNull)
                {

                    MItMeshVertex itvertex = new MItMeshVertex(path, vertice);

                    for (; !itvertex.isDone; itvertex.next())
                    {
                        int index = itvertex.index();

                        mesh.Vertices[index].Traits.SelectedFlag = 1;
                    }

                }

            }

            TriMeshUtil.GroupVertice(mesh);

        }
        // Switching to 3D preview
        private void TabControl_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            e.Handled =true ;
            if ( TabControl1.SelectedIndex == 1 ) { // If the result view was selected
                if ( !ResultGrid.HasItems )
                    SearchButton_Click (null, null) ;
                return ;
            }
            if ( TabControl1.SelectedIndex == 2 ) { // If the 3D view was selected
                ResetUpAxis () ;
                ResetCamera () ;
                ResetLights () ;

                // Reset the model & transform(s)
                this.model.Children.Clear () ;
                //var selected = GetFirstSelected ();
                //// The reason why there might not be a selection is if some tool isn't closed
                //// and prevent the previous selection command from going through
                //if ( selected != null ) {
                //    // If it's a mesh, display it
                //    if ( selected.node.apiTypeStr == "kMesh" ) {
                //        var mesh = new MFnMesh (selected);
                //        // This can take some time, so change the cursor
                //        using ( new CursorSwitcher (null) ) {
                //            model.Children.Add (MakeVisualModel (mesh));
                //        }
                //    }
                //}
                using ( new CursorSwitcher (null) ) {
                    _singleMeshPreviewed =MGlobal.activeSelectionList.length == 1 ;
                    MItSelectionList it =new MItSelectionList (MGlobal.activeSelectionList) ;
                    for ( ; !it.isDone ; it.next () ) {
                        MDagPath path =new MDagPath () ;
                        it.getDagPath (path) ;
                        if ( path.node.apiTypeStr == "kMesh" )
                            model.Children.Add (MakeVisualModel (path)) ;
                    }
                }
                return ;
            }
        }