Beispiel #1
0
        private static void ExtractStandardMeshes(List <MayaM2Mesh> meshList, Dictionary <string, MayaM2Bone> jointMap, List <MayaM2Vertex> globalVertexList)
        {
            for (var meshIter = new MItDag(MItDag.TraversalType.kDepthFirst, MFn.Type.kMesh);
                 !meshIter.isDone; meshIter.next())
            {
                var meshPath = new MDagPath();
                meshIter.getPath(meshPath);

                var meshFn = new MFnMesh(meshPath);
                // only want non-history items
                if (meshFn.isIntermediateObject)
                {
                    continue;
                }
                var name = meshFn.name;
                if (name == "Collision")
                {
                    continue;                     //TODO use custom attribute
                }
                var mesh = new MayaM2Mesh();
                ExtractMeshGeometry(mesh, meshPath, jointMap, globalVertexList);
                ExtractMeshShaders(mesh, meshPath);
                meshList.Add(mesh);
            }
        }
Beispiel #2
0
        /// <summary>
        /// Return true if node descendant hierarchy has any exportable Mesh, Camera, Light or Locator
        /// </summary>
        private bool isNodeRelevantToExportRec(MDagPath mDagPathRoot)
        {
            var       mIteratorType = new MIteratorType();
            MIntArray listOfFilters = new MIntArray();

            listOfFilters.Add((int)MFn.Type.kMesh);
            listOfFilters.Add((int)MFn.Type.kCamera);
            listOfFilters.Add((int)MFn.Type.kLight);
            listOfFilters.Add((int)MFn.Type.kLocator);
            mIteratorType.setFilterList(listOfFilters);
            var dagIterator = new MItDag(mIteratorType, MItDag.TraversalType.kDepthFirst);

            dagIterator.reset(mDagPathRoot);

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

                // Check direct descendants
                if (getApiTypeOfDirectDescendants(mDagPath) != MFn.Type.kUnknown)
                {
                    return(true);
                }

                dagIterator.next();
            }

            // No relevant node found among descendants
            return(false);
        }
Beispiel #3
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="isFull">If true all nodes are printed, otherwise only relevant ones</param>
        private void PrintDAG(bool isFull, MObject root = null)
        {
            var dagIterator = new MItDag(MItDag.TraversalType.kDepthFirst);

            if (root != null)
            {
                dagIterator.reset(root);
            }
            RaiseMessage("DAG: " + (isFull ? "full" : "relevant"));
            while (!dagIterator.isDone)
            {
                MDagPath mDagPath = new MDagPath();
                dagIterator.getPath(mDagPath);

                if (isFull || isNodeRelevantToExportRec(mDagPath) || mDagPath.apiType == MFn.Type.kMesh || mDagPath.apiType == MFn.Type.kCamera || mDagPath.hasFn(MFn.Type.kLight) || mDagPath.apiType == MFn.Type.kLocator)
                {
                    RaiseMessage("name=" + mDagPath.partialPathName + "\t type=" + mDagPath.apiType, (int)dagIterator.depth + 1);
                }
                else
                {
                    dagIterator.prune();
                }
                dagIterator.next();
            }
        }
Beispiel #4
0
        /// <summary>
        /// Extract the vertices, normals and triangles of a mesh into the M2 collision data fields.
        /// </summary>
        /// <param name="wowModel"></param>
        private static void InjectCollisionMesh(M2 wowModel)
        {
            var collisionFound = false;

            for (var meshIter = new MItDag(MItDag.TraversalType.kDepthFirst, MFn.Type.kMesh);
                 !meshIter.isDone; meshIter.next())
            {
                var meshPath = new MDagPath();
                meshIter.getPath(meshPath);

                var meshFn = new MFnMesh(meshPath);
                // only want non-history items
                if (meshFn.isIntermediateObject)
                {
                    continue;
                }
                var name = meshFn.name;
                if (name != "Collision")
                {
                    continue;                     //TODO use custom attribute
                }
                if (collisionFound)
                {
                    throw new Exception("More than one collision box has been found. One supported.");
                }
                MGlobal.displayInfo("\t Collision mesh detected.");

                wowModel.CollisionBox = new CAaBox(AxisInvert(meshFn.boundingBox.min),
                                                   AxisInvert(meshFn.boundingBox.max));
                wowModel.CollisionSphereRadius =
                    (float)Math.Max(meshFn.boundingBox.depth / 2, meshFn.boundingBox.width / 2);

                //TODO fixme better iterate through faces
                var collisionPoints = new MFloatPointArray();
                meshFn.getPoints(collisionPoints, MSpace.Space.kWorld);
                var collisionNormals = new MFloatVectorArray();
                meshFn.getNormals(collisionNormals, MSpace.Space.kWorld);
                var collisionTriangles = new MIntArray();
                meshFn.getTriangles(new MIntArray(), collisionTriangles);
                for (var i = 0; i < collisionPoints.Count; i++)
                {
                    wowModel.CollisionVertices.Add(AxisInvert(collisionPoints[i]));
                    wowModel.CollisionNormals.Add(AxisInvert(collisionNormals[i]));
                }
                foreach (var vertIndex in collisionTriangles)
                {
                    wowModel.CollisionTriangles.Add((ushort)vertIndex);
                }

                collisionFound = true;
            }
        }
        public void Create()
        {
            MItDag jointIterator = new MItDag(MItDag.TraversalType.kDepthFirst, MFn.Type.kJoint);

            //Create Joints and collect their DAG Paths
            short jointID = 0;

            for (; !jointIterator.isDone; jointIterator.next())
            {
                MFnIkJoint ikJoint      = new MFnIkJoint();
                MDagPath   jointDagPath = new MDagPath();

                jointIterator.getPath(jointDagPath);
                this.JointDagPaths.Add(jointDagPath);
                ikJoint.setObject(jointDagPath);

                MTransformationMatrix local         = new MTransformationMatrix(ikJoint.transformationMatrix);
                MTransformationMatrix inverseGlobal = new MTransformationMatrix(jointDagPath.inclusiveMatrixInverse);

                this.Joints.Add(new SKLJoint(jointID, ikJoint.name, local, inverseGlobal));
                this.JointIndices.Add(ELF.Hash(ikJoint.name), jointID);
                jointID++;
            }

            //Set Joint parents
            for (int i = 0; i < this.Joints.Count; i++)
            {
                MFnIkJoint ikJoint = new MFnIkJoint(this.JointDagPaths[i]);
                if (ikJoint.parentCount == 1 && ikJoint.parent(0).apiType == MFn.Type.kJoint)
                {
                    MFnIkJoint parentJoint   = new MFnIkJoint(ikJoint.parent(0));
                    MDagPath   parentDagPath = new MDagPath();

                    parentJoint.getPath(parentDagPath);

                    //Find index of parent
                    for (int j = 0; j < this.JointDagPaths.Count; j++)
                    {
                        if (parentDagPath.equalEqual(this.JointDagPaths[j]))
                        {
                            this.Joints[i].ParentID = (short)j;
                        }
                    }
                }
                else
                {
                    this.Joints[i].ParentID = -1;
                }
            }

            MGlobal.displayInfo("SKLFile:Create - Created SKL File");
        }
Beispiel #6
0
        private void buildXformTree()
        {
            // Get the very root of the Maya DAG.
            MItDag rootIt = new MItDag();

            rootXform.isRoot = true;
            rootXform.name   = "root";
            MFnDagNode rootDagNode = new MFnDagNode(rootIt.root());

            rootDagNode.getPath(rootXform.mayaObjectPath);

            // Process all children transforms of the root.
            processXform(rootXform);
        }
Beispiel #7
0
        /// <summary>
        /// Init the dictionary of the skin. This dictionary represents the skeleton. It contains the node names and their index.
        /// And add it to skinDictionary
        /// </summary>
        /// <param name="skin">the skin cluster</param>
        /// <returns>
        /// The dictionary that represents the skin skeleton
        /// </returns>
        private Dictionary <string, int> GetIndexByFullPathNameDictionary(MFnSkinCluster skin)
        {
            if (skinDictionary.ContainsKey(skin.name))
            {
                return(skinDictionary[skin.name]);
            }
            Dictionary <string, int> indexByFullPathName = new Dictionary <string, int>();
            List <MObject>           revelantNodes       = GetRevelantNodes(skin);

            // get the root node
            MObject rootNode = GetRootNode(skin);
            // Travel the DAG
            MItDag dagIterator = new MItDag(MItDag.TraversalType.kDepthFirst);

            dagIterator.reset(rootNode);
            int index = 0;

            while (!dagIterator.isDone)
            {
                // current node
                MDagPath mDagPath = new MDagPath();
                dagIterator.getPath(mDagPath);
                MObject currentNode = mDagPath.node;

                try
                {
                    if (revelantNodes.Count(node => Equals(node, currentNode)) > 0)
                    {
                        MFnTransform currentNodeTransform = new MFnTransform(currentNode);
                        string       currentFullPathName  = currentNodeTransform.fullPathName;

                        indexByFullPathName.Add(currentFullPathName, index);
                        index++;
                    }
                }
                catch   // When it's not a kTransform or kJoint node. For exemple a kLocator, kNurbsCurve.
                {
                    RaiseError($"{currentNode.apiType} is not supported. It will not be exported: {mDagPath.fullPathName}", 3);
                    return(null);
                }

                dagIterator.next();
            }

            skinDictionary.Add(skin.name, indexByFullPathName);

            return(indexByFullPathName);
        }
        public List<string> getMayaNodesByType(MFnType t)
        {
            List<string> lMayaNodes = new List<string>();
            MItDag itdagn = new MItDag(MItDag.TraversalType.kBreadthFirst, (MFn.Type)t);
            MFnDagNode dagn;

            while (!itdagn.isDone)
            {
                dagn = new MFnDagNode(itdagn.item());
                if(!dagn.isIntermediateObject)
                    lMayaNodes.Add(dagn.partialPathName);
                itdagn.next();
            }

            return lMayaNodes;
        }
Beispiel #9
0
        /*
         * static Action m_update= delegate { };
         * public void SubscribeEvent()
         * {
         * IEvents subscriber = OperationContext.Current.GetCallbackChannel<IEvents>();
         * m_update += subscriber.hasUpdated;
         * }
         *
         * public static void SendUpdateEvent()
         * {
         * m_update();
         * }
         *
         * public void UpdateEvent()
         * {
         * ServiceImplementation.SendUpdateEvent();
         * }
         */

        public List <string> getMayaNodesByType(MFnType t)
        {
            var        lMayaNodes = new List <string>();
            var        itdagn     = new MItDag(MItDag.TraversalType.kBreadthFirst, (MFn.Type)t);
            MFnDagNode dagn;

            while (!itdagn.isDone)
            {
                dagn = new MFnDagNode(itdagn.item());
                if (!dagn.isIntermediateObject)
                {
                    lMayaNodes.Add(dagn.partialPathName);
                }
                itdagn.next();
            }

            return(lMayaNodes);
        }
        protected void initTests(MPx3dModelView view)
        {
            MGlobal.displayInfo("exampleCameraSetViewCmd::initTests");

            clearResults(view);

            //	Add every camera into the scene. Don't change the main camera,
            //	it is OK that it gets reused.
            //
            MFnCameraSet cstFn      = new MFnCameraSet();
            MObject      cstObj     = cstFn.create();
            MDagPath     cameraPath = null;

            MItDag dagIterator = new MItDag(MItDag.TraversalType.kDepthFirst, MFn.Type.kCamera);

            for (; !dagIterator.isDone; dagIterator.next())
            {
                cameraPath = new MDagPath();

                MFnCamera camera;

                try
                {
                    dagIterator.getPath(cameraPath);
                    camera = new MFnCamera(cameraPath);
                }
                catch (Exception)
                {
                    continue;
                }

                fCameraList.append(cameraPath);

                cstFn.appendLayer(cameraPath, MObject.kNullObj);

                MGlobal.displayInfo(camera.fullPathName());
            }

            view.setCameraSet(cstObj);
            view.refresh();
        }
		protected void initTests(MPx3dModelView view)
		{
			MGlobal.displayInfo("exampleCameraSetViewCmd::initTests");

			clearResults(view);

			//	Add every camera into the scene. Don't change the main camera,
			//	it is OK that it gets reused.
			//
			MFnCameraSet cstFn = new MFnCameraSet();
			MObject cstObj = cstFn.create();
			MDagPath cameraPath = null;
			
			MItDag dagIterator = new MItDag(MItDag.TraversalType.kDepthFirst, MFn.Type.kCamera);
			for (; !dagIterator.isDone; dagIterator.next())
			{
				cameraPath = new MDagPath();

				MFnCamera camera;

				try
				{
					dagIterator.getPath(cameraPath);
					camera = new MFnCamera(cameraPath);
				}
				catch (Exception)
				{
					continue;
				}

				fCameraList.append(cameraPath);

				cstFn.appendLayer(cameraPath, MObject.kNullObj);

				MGlobal.displayInfo(camera.fullPathName());
			}

			view.setCameraSet(cstObj);
			view.refresh();
		}
Beispiel #12
0
		private void parseArgs( MArgList args,ref MItDag.TraversalType traversalType,
			MFn.Type filter, ref bool quiet)
		{
			string arg = "";
			const string breadthFlag = "-b";
			const string breadthFlagLong = "-breadthFirst";
			const string depthFlag = "-d";
			const string depthFlagLong = "-depthFirst";
			const string cameraFlag = "-c";
			const string cameraFlagLong = "-cameras";
			const string lightFlag = "-l";
			const string lightFlagLong = "-lights";
			const string nurbsSurfaceFlag = "-n";
			const string nurbsSurfaceFlagLong = "-nurbsSurfaces";
			const string quietFlag = "-q";
			const string quietFlagLong = "-quiet";

			for (uint i = 0; i < args.length; i++)
			{
				arg = args.asString(i);
				if ( arg == breadthFlag || arg == breadthFlagLong )
					traversalType = MItDag.TraversalType.kBreadthFirst;
				else if ( arg == depthFlag || arg == depthFlagLong )
					traversalType = MItDag.TraversalType.kDepthFirst;
				else if ( arg == cameraFlag || arg == cameraFlagLong )
					filter = MFn.Type.kCamera;
				else if ( arg == lightFlag || arg == lightFlagLong )
					filter = MFn.Type.kLight;
				else if ( arg == nurbsSurfaceFlag || arg == nurbsSurfaceFlagLong )
					filter = MFn.Type.kNurbsSurface;
				else if ( arg == quietFlag || arg == quietFlagLong )
					quiet = true;
				else {
					arg += ": unknown argument";
					throw new ArgumentException(arg, "args");
				}
			}
		}
Beispiel #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)
        {
            // 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);
        }
Beispiel #14
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);
        }
Beispiel #15
0
        public void Export(string outputDirectory, string outputFileName, string outputFormat, bool generateManifest, bool onlySelected, bool autoSaveMayaFile, bool exportHiddenObjects, bool copyTexturesToOutput)
        {
            RaiseMessage("Exportation started", Color.Blue);
            var progression = 0.0f;

            ReportProgressChanged(progression);

            // Store export options
            _onlySelected        = onlySelected;
            _exportHiddenObjects = exportHiddenObjects;
            isBabylonExported    = outputFormat == "babylon" || outputFormat == "binary babylon";

            // 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");
                // TODO
                //MFileIO.save();
            }

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

            // Producer
            babylonScene.producer = new BabylonProducer
            {
                name             = "Maya",
                version          = "2018",
                exporter_version = "1.0",
                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;

            // --------------------
            // ------ Meshes ------
            // --------------------
            RaiseMessage("Exporting meshes");
            // Get all meshes
            var            dagIterator = new MItDag(MItDag.TraversalType.kDepthFirst, MFn.Type.kMesh);
            List <MObject> mObjects    = new List <MObject>();

            while (!dagIterator.isDone)
            {
                var mObject = dagIterator.currentItem();
                mObjects.Add(mObject);
                dagIterator.next();
            }
            // Export all meshes
            var progressionStep = 100.0f / mObjects.Count;

            foreach (MObject mObject in mObjects)
            {
                ExportMesh(mObject, babylonScene);

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

            dagIterator = new MItDag(MItDag.TraversalType.kDepthFirst, MFn.Type.kMesh);

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

            // --------------------
            // ----- Materials ----
            // --------------------
            // TODO - Materials

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

            // TODO - Export glTF

            watch.Stop();
            RaiseMessage(string.Format("Exportation done in {0:0.00}s", watch.ElapsedMilliseconds / 1000.0), Color.Blue);
        }
Beispiel #16
0
		protected void writeReferenceNodes(FileStream f)
		{
			//
			// We don't write out createNode commands for reference nodes, but
			// we do write out parenting between them and non-reference nodes,
			// as well as attributes added and attribute values changed after the
			// referenced file was loaded
			//
			writeRefNodeParenting(f);

			//
			// Output the commands for DAG nodes first.
			//
			MItDag	dagIter = new MItDag();

			for (dagIter.next(); !dagIter.isDone; dagIter.next())
			{
				MObject				node = dagIter.item();
				MFnDependencyNode	nodeFn = new MFnDependencyNode(node);

				if (nodeFn.isFromReferencedFile
				&&	!nodeFn.isFlagSet(fAttrFlag))
				{
					writeNodeAttrs(f, node, false);

					//
					// Make note of any connections to this node which have been
					// broken by the main scene.
					//
					MFileIO.getReferenceConnectionsBroken(
						node, fBrokenConnSrcs, fBrokenConnDests, true, true
					);

					nodeFn.setFlag(fAttrFlag, true);
				}
			}

			//
			// Now do the remaining, non-DAG nodes.
			//
			MItDependencyNodes	nodeIter = new MItDependencyNodes();

			for (; !nodeIter.isDone; nodeIter.next())
			{
				MObject				node = nodeIter.item;
				MFnDependencyNode	nodeFn = new MFnDependencyNode(node);

				if (nodeFn.isFromReferencedFile
				&&	!nodeFn.isFlagSet(fAttrFlag))
				{
					writeNodeAttrs(f, node, false);

					//
					// Make note of any connections to this node which have been
					// broken by the main scene.
					//
					MFileIO.getReferenceConnectionsBroken(
						node, fBrokenConnSrcs, fBrokenConnDests, true, true
					);

					nodeFn.setFlag(fAttrFlag, true);
				}
			}
		}
Beispiel #17
0
		//
		// Write out all of the connections in the scene.
		//
		protected void writeConnections(FileStream f)
		{
			//
			// If the scene has broken any connections which were made in referenced
			// files, handle those first so that the attributes are free for any new
			// connections which may come along.
			//
			writeBrokenRefConnections(f);

			//
			// We're about to write out the scene's connections in three parts: DAG
			// nodes, non-DAG non-default nodes, then default nodes.
			//
			// It's really not necessary that we group them like this and would in
			// fact be more efficient to do them all in one MItDependencyNodes
			// traversal.  However, this is the order in which the normal MayaAscii
			// translator does them, so this makes it easier to compare the output
			// of this translator to Maya's output.
			//

			//
			// Write out connections for the DAG nodes first.
			//
			MItDag	dagIter = new MItDag();
			dagIter.traverseUnderWorld(true);

			for (dagIter.next(); !dagIter.isDone; dagIter.next())
			{
				MObject		node = dagIter.item();
				MFnDagNode	dagNodeFn = new MFnDagNode(node);

				if (!dagNodeFn.isFlagSet(fConnectionFlag)
				&&	dagNodeFn.canBeWritten
				&&	!dagNodeFn.isDefaultNode)
				{
					writeNodeConnections(f, dagIter.item());
					dagNodeFn.setFlag(fConnectionFlag, true);
				}
			}

			//
			// Now do the non-DAG, non-default nodes.
			//
			MItDependencyNodes	nodeIter = new MItDependencyNodes();

			for (; !nodeIter.isDone; nodeIter.next())
			{
				MFnDependencyNode	nodeFn = new MFnDependencyNode(nodeIter.item);

				if (!nodeFn.isFlagSet(fConnectionFlag)
				&&	nodeFn.canBeWritten
				&&	!nodeFn.isDefaultNode)
				{
					writeNodeConnections(f, nodeIter.item);
					nodeFn.setFlag(fConnectionFlag, true);
				}
			}

			//
			// And finish up with the default nodes.
			//
			uint numNodes = fDefaultNodes.length;
			int i;

			for (i = 0; i < numNodes; i++)
			{
				MFnDependencyNode	nodeFn = new MFnDependencyNode(fDefaultNodes[i]);

				if (!nodeFn.isFlagSet(fConnectionFlag)
				&&	nodeFn.canBeWritten
				&&	nodeFn.isDefaultNode)
				{
					writeNodeConnections(f, fDefaultNodes[i]);
					nodeFn.setFlag(fConnectionFlag, true);
				}
			}
		}
        public void ResetLights()
        {
            //<AmbientLight Color="White" />
            //<DirectionalLight Color="White" Direction="-1,-1,-1" />
            //<PointLight Color="White" ConstantAttenuation="1" LinearAttenuation="1" Position="0,0,0" QuadraticAttenuation="1" Range="0" />
            //<SpotLight Color="White" ConstantAttenuation="1" Direction="-1,-1,-1" InnerConeAngle="10" LinearAttenuation="1" OuterConeAngle="10" Position="0,0,0" QuadraticAttenuation="1" Range="0" />
            lights.Children.Clear () ;

            MItDag dagIterator =new MItDag (MItDag.TraversalType.kDepthFirst, MFn.Type.kLight) ;
            for ( ; !dagIterator.isDone ; dagIterator.next () ) {
                MDagPath lightPath =new MDagPath () ;
                dagIterator.getPath (lightPath) ;

                MFnLight light =new MFnLight (lightPath) ;
                bool isAmbient =light.lightAmbient ;
                MColor mcolor =light.color ;
                Color color =Color.FromScRgb (1.0f, mcolor.r, mcolor.g, mcolor.b) ;
                if ( isAmbient ) {
                    AmbientLight ambient =new AmbientLight (color) ;
                    lights.Children.Add (ambient) ;
                    continue ;
                }

                MFloatVector lightDirection =light.lightDirection (0, MSpace.Space.kWorld) ;
                Vector3D direction =new Vector3D (lightDirection.x, lightDirection.y, lightDirection.z) ;
                bool isDiffuse =light.lightDiffuse ;
                try {
                    MFnDirectionalLight dirLight =new MFnDirectionalLight (lightPath) ;
                    DirectionalLight directional =new DirectionalLight (color, direction) ;
                    lights.Children.Add (directional) ;
                    continue ;
                } catch {
                }

                MObject transformNode =lightPath.transform ;
                MFnDagNode transform =new MFnDagNode (transformNode) ;
                MTransformationMatrix matrix =new MTransformationMatrix (transform.transformationMatrix) ;
                double [] threeDoubles =new double [3] ;
                int rOrder =0 ; //MTransformationMatrix.RotationOrder rOrder ;
                matrix.getRotation (threeDoubles, out rOrder, MSpace.Space.kWorld) ;
                matrix.getScale (threeDoubles, MSpace.Space.kWorld) ;
                MVector pos =matrix.getTranslation (MSpace.Space.kWorld) ;
                Point3D position =new Point3D (pos.x, pos.y, pos.z) ;
                try {
                    MFnPointLight pointLight =new MFnPointLight (lightPath) ;
                    PointLight point =new PointLight (color, position) ;
                    //point.ConstantAttenuation =pointLight. ; // LinearAttenuation / QuadraticAttenuation
                    //point.Range =pointLight.rayDepthLimit ;
                    lights.Children.Add (point) ;
                    continue ;
                } catch {
                }

                try {
                    MFnSpotLight spotLight =new MFnSpotLight (lightPath) ;
                    MAngle InnerConeAngle =new MAngle (spotLight.coneAngle) ;
                    MAngle OuterConeAngle =new MAngle (spotLight.penumbraAngle) ;
                    SpotLight spot =new SpotLight (color, position, direction, OuterConeAngle.asDegrees, InnerConeAngle.asDegrees) ;
                    spot.ConstantAttenuation =spotLight.dropOff ; // LinearAttenuation / QuadraticAttenuation
                    //spot.Range =spotLight.rayDepthLimit ;
                    lights.Children.Add (spot) ;
                    continue ;
                } catch {
                }
            }
        }
Beispiel #19
0
		protected void writeDagNodes(FileStream f)
		{
			fParentingRequired.clear();

			MItDag	dagIter = new MItDag();

			dagIter.traverseUnderWorld(true);

			MDagPath worldPath = new MDagPath();

			dagIter.getPath(worldPath);

			//
			// We step over the world node before starting the loop, because it
			// doesn't get written out.
			//
			for (dagIter.next(); !dagIter.isDone; dagIter.next())
			{
				MDagPath	path = new MDagPath();
				dagIter.getPath(path);

				//
				// If the node has already been written, then all of its descendants
				// must have been written, or at least checked, as well, so prune
				// this branch of the tree from the iteration.
				//
				MFnDagNode	dagNodeFn = new MFnDagNode(path);

				if (dagNodeFn.isFlagSet(fCreateFlag))
				{
					dagIter.prune();
					continue;
				}

				//
				// If this is a default node, it will be written out later, so skip
				// it.
				//
				if (dagNodeFn.isDefaultNode) continue;

				//
				// If this node is not writable, and is not a shared node, then mark
				// it as having been written, and skip it.
				//
				if (!dagNodeFn.canBeWritten && !dagNodeFn.isShared)
				{
					dagNodeFn.setFlag(fCreateFlag, true);
					continue;
				}

				uint numParents = dagNodeFn.parentCount;

				if (dagNodeFn.isFromReferencedFile)
				{
					//
					// We don't issue 'creatNode' commands for nodes from referenced
					// files, but if the node has any parents which are not from
					// referenced files, other than the world, then make a note that
					// we'll need to issue extra 'parent' commands for it later on.
					//
					uint i;

					for (i = 0; i < numParents; i++)
					{
						MObject		altParent = dagNodeFn.parent(i);
						MFnDagNode	altParentFn = new MFnDagNode(altParent);

						if (!altParentFn.isFromReferencedFile
						&&	(altParentFn.objectProperty.notEqual(worldPath.node)))
						{
							fParentingRequired.append(path);
							break;
						}
					}
				}
				else
				{
					//
					// Find the node's parent.
					//
					MDagPath parentPath = new MDagPath(worldPath);

					if (path.length > 1)
					{
						//
						// Get the parent's path.
						//
						parentPath.assign(path);
						parentPath.pop();

						//
						// If the parent is in the underworld, then find the closest
						// ancestor which is not.
						//
						if (parentPath.pathCount > 1)
						{
							//
							// The first segment of the path contains whatever
							// portion of the path exists in the world.  So the closest
							// worldly ancestor is simply the one at the end of that
							// first path segment.
							//
							path.getPath(parentPath, 0);
						}
					}

					MFnDagNode	parentNodeFn = new MFnDagNode(parentPath);

					if (parentNodeFn.isFromReferencedFile)
					{
						//
						// We prefer to parent to a non-referenced node.  So if this
						// node has any other parents, which are not from referenced
						// files and have not already been processed, then we'll
						// skip this instance and wait for an instance through one
						// of those parents.
						//
						uint i;

						for (i = 0; i < numParents; i++)
						{
							if (dagNodeFn.parent(i).notEqual(parentNodeFn.objectProperty))
							{
								MObject		altParent = dagNodeFn.parent(i);
								MFnDagNode	altParentFn = new MFnDagNode(altParent);

								if (!altParentFn.isFromReferencedFile
								&&	!altParentFn.isFlagSet(fCreateFlag))
								{
									break;
								}
							}
						}

						if (i < numParents) continue;

						//
						// This node only has parents within referenced files, so
						// create it without a parent and note that we need to issue
						// 'parent' commands for it later on.
						//
						writeCreateNode(f, path, worldPath);

						fParentingRequired.append(path);
					}
					else
					{
						writeCreateNode(f, path, parentPath);

						//
						// Let's see if this node has any parents from referenced
						// files, or any parents other than this one which are not
						// from referenced files.
						//
						uint i;
						bool hasRefParents = false;
						bool hasOtherNonRefParents = false;

						for (i = 0; i < numParents; i++)
						{
							if (dagNodeFn.parent(i).notEqual(parentNodeFn.objectProperty))
							{
								MObject		altParent = dagNodeFn.parent(i);
								MFnDagNode	altParentFn = new MFnDagNode(altParent);

								if (altParentFn.isFromReferencedFile)
									hasRefParents = true;
								else
									hasOtherNonRefParents = true;

								//
								// If we've already got positives for both tests,
								// then there's no need in continuing.
								//
								if (hasRefParents && hasOtherNonRefParents) break;
							}
						}

						//
						// If this node has parents from referenced files, then
						// make note that we will have to issue 'parent' commands
						// later on.
						//
						if (hasRefParents) fParentingRequired.append(path);

						//
						// If this node has parents other than this one which are
						// not from referenced files, then make note that the
						// parenting for the other instances still has to be done.
						//
						if (hasOtherNonRefParents)
						{
							fInstanceChildren.append(path);
							fInstanceParents.append(parentPath);
						}
					}

					//
					// Write out the node's 'addAttr', 'setAttr' and 'lockNode'
					// commands.
					//
					writeNodeAttrs(f, path.node, true);
					writeLockNode(f, path.node);
				}

				//
				// Mark the node as having been written.
				//
				dagNodeFn.setFlag(fCreateFlag, true);
			}

			//
			// Write out the parenting for instances.
			//
			writeInstances(f);
		}
Beispiel #20
0
        private void buildXformTree()
        {
            // Get the very root of the Maya DAG.
            MItDag rootIt = new MItDag();
            rootXform.isRoot = true;
            rootXform.name = "root";
            MFnDagNode rootDagNode = new MFnDagNode(rootIt.root());
            rootDagNode.getPath(rootXform.mayaObjectPath);

            // Process all children transforms of the root.
            processXform(rootXform);
        }
Beispiel #21
0
        public void ResetLights()
        {
            //<AmbientLight Color="White" />
            //<DirectionalLight Color="White" Direction="-1,-1,-1" />
            //<PointLight Color="White" ConstantAttenuation="1" LinearAttenuation="1" Position="0,0,0" QuadraticAttenuation="1" Range="0" />
            //<SpotLight Color="White" ConstantAttenuation="1" Direction="-1,-1,-1" InnerConeAngle="10" LinearAttenuation="1" OuterConeAngle="10" Position="0,0,0" QuadraticAttenuation="1" Range="0" />
            lights.Children.Clear();

            MItDag dagIterator = new MItDag(MItDag.TraversalType.kDepthFirst, MFn.Type.kLight);

            for ( ; !dagIterator.isDone; dagIterator.next())
            {
                MDagPath lightPath = new MDagPath();
                dagIterator.getPath(lightPath);

                MFnLight light     = new MFnLight(lightPath);
                bool     isAmbient = light.lightAmbient;
                MColor   mcolor    = light.color;
                Color    color     = Color.FromScRgb(1.0f, mcolor.r, mcolor.g, mcolor.b);
                if (isAmbient)
                {
                    AmbientLight ambient = new AmbientLight(color);
                    lights.Children.Add(ambient);
                    continue;
                }

                MFloatVector lightDirection = light.lightDirection(0, MSpace.Space.kWorld);
                Vector3D     direction      = new Vector3D(lightDirection.x, lightDirection.y, lightDirection.z);
                bool         isDiffuse      = light.lightDiffuse;
                try {
                    MFnDirectionalLight dirLight    = new MFnDirectionalLight(lightPath);
                    DirectionalLight    directional = new DirectionalLight(color, direction);
                    lights.Children.Add(directional);
                    continue;
                } catch {
                }

                MObject               transformNode = lightPath.transform;
                MFnDagNode            transform     = new MFnDagNode(transformNode);
                MTransformationMatrix matrix        = new MTransformationMatrix(transform.transformationMatrix);
                double []             threeDoubles  = new double [3];
                int rOrder = 0;                 //MTransformationMatrix.RotationOrder rOrder ;
                matrix.getRotation(threeDoubles, out rOrder, MSpace.Space.kWorld);
                matrix.getScale(threeDoubles, MSpace.Space.kWorld);
                MVector pos      = matrix.getTranslation(MSpace.Space.kWorld);
                Point3D position = new Point3D(pos.x, pos.y, pos.z);
                try {
                    MFnPointLight pointLight = new MFnPointLight(lightPath);
                    PointLight    point      = new PointLight(color, position);
                    //point.ConstantAttenuation =pointLight. ; // LinearAttenuation / QuadraticAttenuation
                    //point.Range =pointLight.rayDepthLimit ;
                    lights.Children.Add(point);
                    continue;
                } catch {
                }

                try {
                    MFnSpotLight spotLight      = new MFnSpotLight(lightPath);
                    MAngle       InnerConeAngle = new MAngle(spotLight.coneAngle);
                    MAngle       OuterConeAngle = new MAngle(spotLight.penumbraAngle);
                    SpotLight    spot           = new SpotLight(color, position, direction, OuterConeAngle.asDegrees, InnerConeAngle.asDegrees);
                    spot.ConstantAttenuation = spotLight.dropOff;                     // LinearAttenuation / QuadraticAttenuation
                    //spot.Range =spotLight.rayDepthLimit ;
                    lights.Children.Add(spot);
                    continue;
                } catch {
                }
            }
        }
Beispiel #22
0
        private void doScan(MItDag.TraversalType traversalType, MFn.Type filter, bool quiet)
        {
            MItDag dagIterator = new MItDag(traversalType, filter);

            //	Scan the entire DAG and output the name and depth of each node

            if (traversalType == MItDag.TraversalType.kBreadthFirst)
                if (!quiet)
                    MGlobal.displayInfo(Environment.NewLine + "Starting Breadth First scan of the Dag");
            else
                if (!quiet)
                    MGlobal.displayInfo(Environment.NewLine + "Starting Depth First scan of the Dag");

            switch (filter)
            {
                case MFn.Type.kCamera:
                    if (!quiet)
                        MGlobal.displayInfo( ": Filtering for Cameras\n");
                    break;
                case MFn.Type.kLight:
                    if (!quiet)
                        MGlobal.displayInfo(": Filtering for Lights\n");
                    break;
                case MFn.Type.kNurbsSurface:
                    if (!quiet)
                        MGlobal.displayInfo(": Filtering for Nurbs Surfaces\n");
                    break;
                default:
                    MGlobal.displayInfo(Environment.NewLine);
                    break;
            }

            int objectCount = 0;
            for ( ; !dagIterator.isDone; dagIterator.next() ) {

                MDagPath dagPath = new MDagPath();

                try
                {
                    dagIterator.getPath(dagPath);
                }
                catch (System.Exception )
                {
                    continue;
                }

                MFnDagNode dagNode = null;
                try
                {
                    dagNode = new MFnDagNode(dagPath);
                }
                catch (System.Exception )
                {
                    continue;
                }

                if (!quiet)
                    MGlobal.displayInfo(dagNode.name + ": " + dagNode.typeName + Environment.NewLine);

                if (!quiet)
                    MGlobal.displayInfo( "  dagPath: " + dagPath.fullPathName + Environment.NewLine);

                objectCount += 1;
                if (dagPath.hasFn(MFn.Type.kCamera))
                {
                    MFnCamera camera  =  null;
                    try
                    {
                        camera  = new MFnCamera(dagPath);
                    }
                    catch (System.Exception)
                    {
                        continue;
                    }

                    // Get the translation/rotation/scale data
                    //
                    printTransformData(dagPath, quiet);

                    // Extract some interesting Camera data
                    //
                    if (!quiet)
                    {

                        MGlobal.displayInfo("  eyePoint: " + MPointToString(camera.eyePoint(MSpace.Space.kWorld)) + Environment.NewLine);

                        MGlobal.displayInfo("  upDirection: " + MVectorToString( camera.upDirection(MSpace.Space.kWorld)) + Environment.NewLine);

                        MGlobal.displayInfo("  viewDirection: " + MVectorToString( camera.viewDirection(MSpace.Space.kWorld)) + Environment.NewLine);

                        MGlobal.displayInfo("  aspectRatio: " + Convert.ToString( camera.aspectRatio ) + Environment.NewLine);

                        MGlobal.displayInfo("  horizontalFilmAperture: " + Convert.ToString(camera.horizontalFilmAperture ) + Environment.NewLine);

                        MGlobal.displayInfo("  verticalFilmAperture: " + Convert.ToString(camera.verticalFilmAperture ) + Environment.NewLine);
                    }
                }
                else if (dagPath.hasFn(MFn.Type.kLight))
                {
                    MFnLight light = null;
                    try
                    {
                        light = new MFnLight(dagPath);
                    }
                    catch (System.Exception)
                    {
                        continue;
                    }

                    // Get the translation/rotation/scale data
                    //
                    printTransformData(dagPath, quiet);

                    // Extract some interesting Light data
                    //
                    MColor color = light.color;
                    if (!quiet)
                    {
                        MGlobal.displayInfo(string.Format("  color: [%f, %f, %f]\n", color.r, color.g, color.b));
                    }
                    color = light.shadowColor;
                    if (!quiet)
                    {

                        MGlobal.displayInfo(string.Format("  shadowColor: [%f, %f, %f]\n", color.r, color.g, color.b));
                        MGlobal.displayInfo("  intensity: "+Convert.ToString(light.intensity) + Environment.NewLine);

                    }
                }
                else if (dagPath.hasFn(MFn.Type.kNurbsSurface))
                {
                    MFnNurbsSurface surface= null;
                    try
                    {
                        surface = new MFnNurbsSurface(dagPath);
                    }
                    catch (System.Exception )
                    {
                        continue;
                    }

                    // Get the translation/rotation/scale data
                    //
                    printTransformData(dagPath, quiet);

                    // Extract some interesting Surface data
                    //
                    if (!quiet)
                    {
                        MGlobal.displayInfo(string.Format("  numCVs: %d * %s", surface.numCVsInU, surface.numCVsInV) + Environment.NewLine);
                        MGlobal.displayInfo(string.Format("  numKnots: %d * %s\n", surface.numKnotsInU, surface.numKnotsInV) + Environment.NewLine);
                        MGlobal.displayInfo(string.Format("  numSpans: %d * %s\n", surface.numSpansInU, surface.numSpansInV) + Environment.NewLine);
                    }
                } else
                {
                    // Get the translation/rotation/scale data
                    //
                    printTransformData(dagPath, quiet);
                }
            }

            setResult(objectCount);
        }
Beispiel #23
0
        private void doScan(MItDag.TraversalType traversalType, MFn.Type filter, bool quiet)
        {
            MItDag dagIterator = new MItDag(traversalType, filter);

            //	Scan the entire DAG and output the name and depth of each node

            if (traversalType == MItDag.TraversalType.kBreadthFirst)
            {
                if (!quiet)
                {
                    MGlobal.displayInfo(Environment.NewLine + "Starting Breadth First scan of the Dag");
                }
                else
                if (!quiet)
                {
                    MGlobal.displayInfo(Environment.NewLine + "Starting Depth First scan of the Dag");
                }
            }

            switch (filter)
            {
            case MFn.Type.kCamera:
                if (!quiet)
                {
                    MGlobal.displayInfo(": Filtering for Cameras\n");
                }
                break;

            case MFn.Type.kLight:
                if (!quiet)
                {
                    MGlobal.displayInfo(": Filtering for Lights\n");
                }
                break;

            case MFn.Type.kNurbsSurface:
                if (!quiet)
                {
                    MGlobal.displayInfo(": Filtering for Nurbs Surfaces\n");
                }
                break;

            default:
                MGlobal.displayInfo(Environment.NewLine);
                break;
            }


            int objectCount = 0;

            for ( ; !dagIterator.isDone; dagIterator.next())
            {
                MDagPath dagPath = new MDagPath();

                try
                {
                    dagIterator.getPath(dagPath);
                }
                catch (System.Exception)
                {
                    continue;
                }

                MFnDagNode dagNode = null;
                try
                {
                    dagNode = new MFnDagNode(dagPath);
                }
                catch (System.Exception)
                {
                    continue;
                }

                if (!quiet)
                {
                    MGlobal.displayInfo(dagNode.name + ": " + dagNode.typeName + Environment.NewLine);
                }

                if (!quiet)
                {
                    MGlobal.displayInfo("  dagPath: " + dagPath.fullPathName + Environment.NewLine);
                }

                objectCount += 1;
                if (dagPath.hasFn(MFn.Type.kCamera))
                {
                    MFnCamera camera = null;
                    try
                    {
                        camera = new MFnCamera(dagPath);
                    }
                    catch (System.Exception)
                    {
                        continue;
                    }

                    // Get the translation/rotation/scale data
                    //
                    printTransformData(dagPath, quiet);

                    // Extract some interesting Camera data
                    //
                    if (!quiet)
                    {
                        MGlobal.displayInfo("  eyePoint: " + MPointToString(camera.eyePoint(MSpace.Space.kWorld)) + Environment.NewLine);

                        MGlobal.displayInfo("  upDirection: " + MVectorToString(camera.upDirection(MSpace.Space.kWorld)) + Environment.NewLine);

                        MGlobal.displayInfo("  viewDirection: " + MVectorToString(camera.viewDirection(MSpace.Space.kWorld)) + Environment.NewLine);

                        MGlobal.displayInfo("  aspectRatio: " + Convert.ToString(camera.aspectRatio) + Environment.NewLine);

                        MGlobal.displayInfo("  horizontalFilmAperture: " + Convert.ToString(camera.horizontalFilmAperture) + Environment.NewLine);

                        MGlobal.displayInfo("  verticalFilmAperture: " + Convert.ToString(camera.verticalFilmAperture) + Environment.NewLine);
                    }
                }
                else if (dagPath.hasFn(MFn.Type.kLight))
                {
                    MFnLight light = null;
                    try
                    {
                        light = new MFnLight(dagPath);
                    }
                    catch (System.Exception)
                    {
                        continue;
                    }

                    // Get the translation/rotation/scale data
                    //
                    printTransformData(dagPath, quiet);

                    // Extract some interesting Light data
                    //
                    MColor color = light.color;
                    if (!quiet)
                    {
                        MGlobal.displayInfo(string.Format("  color: [%f, %f, %f]\n", color.r, color.g, color.b));
                    }
                    color = light.shadowColor;
                    if (!quiet)
                    {
                        MGlobal.displayInfo(string.Format("  shadowColor: [%f, %f, %f]\n", color.r, color.g, color.b));
                        MGlobal.displayInfo("  intensity: " + Convert.ToString(light.intensity) + Environment.NewLine);
                    }
                }
                else if (dagPath.hasFn(MFn.Type.kNurbsSurface))
                {
                    MFnNurbsSurface surface = null;
                    try
                    {
                        surface = new MFnNurbsSurface(dagPath);
                    }
                    catch (System.Exception)
                    {
                        continue;
                    }

                    // Get the translation/rotation/scale data
                    //
                    printTransformData(dagPath, quiet);

                    // Extract some interesting Surface data
                    //
                    if (!quiet)
                    {
                        MGlobal.displayInfo(string.Format("  numCVs: %d * %s", surface.numCVsInU, surface.numCVsInV) + Environment.NewLine);
                        MGlobal.displayInfo(string.Format("  numKnots: %d * %s\n", surface.numKnotsInU, surface.numKnotsInV) + Environment.NewLine);
                        MGlobal.displayInfo(string.Format("  numSpans: %d * %s\n", surface.numSpansInU, surface.numSpansInV) + Environment.NewLine);
                    }
                }
                else
                {
                    // Get the translation/rotation/scale data
                    //
                    printTransformData(dagPath, quiet);
                }
            }

            setResult(objectCount);
        }
Beispiel #24
0
        private static Dictionary <string, MayaM2Bone> ExtractJoints(List <MayaM2Sequence> seqList)
        {
            var jointMap = new Dictionary <string, MayaM2Bone>();

            //Goal of iteration : Extract raw joint data and store it in intermediate object, MayaM2Bone
            var processedJoints = new HashSet <string>();

            for (var jointIter = new MItDag(MItDag.TraversalType.kDepthFirst, MFn.Type.kJoint); !jointIter.isDone; jointIter.next())
            {
                var jointPath = new MDagPath();
                jointIter.getPath(jointPath);
                if (processedJoints.Contains(jointPath.fullPathName))
                {
                    continue;
                }
                MGlobal.displayInfo("Extracting raw data of " + jointPath.fullPathName);
                var joint    = new MFnIkJoint(jointPath);
                var mayaBone = new MayaM2Bone();
                jointMap[jointPath.fullPathName] = mayaBone;

                // Hierarchy
                var isRoot = joint.parentCount == 0 || !joint.parent(0).hasFn(MFn.Type.kJoint);
                if (!isRoot)
                {
                    var parentPath = new MDagPath();
                    MDagPath.getAPathTo(joint.parent(0), parentPath);
                    if (!jointMap.ContainsKey(parentPath.fullPathName))
                    {
                        MGlobal.displayError("\tParent is not referenced. Crash incoming. Path : " + parentPath.fullPathName);
                    }
                    jointMap[jointPath.fullPathName].Parent = jointMap[parentPath.fullPathName];
                }
                //Note : M2Bone.submesh_id is wrong in the wiki. Do not try to compute it.
                // Label
                jointMap[jointPath.fullPathName].Type      = MGlobal.executeCommandStringResult("getAttr -asString " + joint.fullPathName + ".type");
                jointMap[jointPath.fullPathName].OtherType = MGlobal.executeCommandStringResult("getAttr -asString " + joint.fullPathName + ".otherType");
                jointMap[jointPath.fullPathName].Side      = MGlobal.executeCommandStringResult("getAttr -asString " + joint.fullPathName + ".side");

                // Base translation is used to compute position
                MAnimControl.currentTime = 0;
                jointMap[jointPath.fullPathName].BaseTranslation = joint.getTranslation(MSpace.Space.kTransform);

                foreach (var seq in seqList)
                {
                    var transData = new List <Tuple <uint, MVector> >();
                    var rotData   = new List <Tuple <uint, MQuaternion> >();
                    var scaleData = new List <Tuple <uint, MVector> >();
                    for (var i = seq.Start; i < seq.End; i += 33) //TODO FIXME What if not multiple of 33 ?
                    {
                        //Get data for this joint for this frame
                        MAnimControl.currentTime = new MTime(i, MTime.Unit.kMilliseconds);

                        var translation = joint.getTranslation(MSpace.Space.kTransform);
                        var rotation    = new MQuaternion();
                        joint.getRotation(rotation, MSpace.Space.kTransform);
                        var scaleArray = new double[3];
                        joint.getScale(scaleArray);
                        var scale = new MVector(scaleArray);

                        if (!translation.isEquivalent(MVector.zero, Epsilon))
                        {
                            var previousIsTheSame = transData.Count > 0 &&
                                                    transData.Last().Item2.isEquivalent(translation, Epsilon);
                            if (!previousIsTheSame)
                            {
                                transData.Add(new Tuple <uint, MVector>((uint)(i - seq.Start), translation));
                            }
                        }
                        if (!rotation.isEquivalent(MQuaternion.identity, Epsilon))
                        {
                            var previousIsTheSame = rotData.Count > 0 &&
                                                    rotData.Last().Item2.isEquivalent(rotation, Epsilon);
                            if (!previousIsTheSame)
                            {
                                rotData.Add(new Tuple <uint, MQuaternion>((uint)(i - seq.Start), rotation));
                            }
                        }
                        if (!scale.isEquivalent(MVector.one, Epsilon))
                        {
                            var previousIsTheSame = scaleData.Count > 0 &&
                                                    scaleData.Last().Item2.isEquivalent(scale, Epsilon);
                            if (!previousIsTheSame)
                            {
                                scaleData.Add(new Tuple <uint, MVector>((uint)(i - seq.Start), scale));
                            }
                        }
                    }
                    if (transData.Count > 0)
                    {
                        jointMap[joint.fullPathName].Translation.Add(transData);
                    }
                    if (rotData.Count > 0)
                    {
                        jointMap[joint.fullPathName].Rotation.Add(rotData);
                    }
                    if (scaleData.Count > 0)
                    {
                        jointMap[joint.fullPathName].Scale.Add(scaleData);
                    }
                }


                processedJoints.Add(jointPath.fullPathName);
            }

            //Goal of iteration : apply transformations to joint data & their children
            processedJoints.Clear();
            for (var jointIter = new MItDag(MItDag.TraversalType.kBreadthFirst, MFn.Type.kJoint);
                 !jointIter.isDone;
                 jointIter.next())
            {
                var jointPath = new MDagPath();
                jointIter.getPath(jointPath);
                if (processedJoints.Contains(jointPath.fullPathName))
                {
                    continue;
                }
                MGlobal.displayInfo("Applying joint orient of " + jointPath.fullPathName);
                var joint       = new MFnIkJoint(jointPath);
                var jointOrient = new MQuaternion();
                joint.getOrientation(jointOrient);

                for (uint i = 0; i < joint.childCount; i++)
                {
                    if (!joint.child(i).hasFn(MFn.Type.kJoint))
                    {
                        continue;
                    }
                    var childFn = new MFnIkJoint(joint.child(i));
                    MGlobal.displayInfo("\tto " + childFn.fullPathName + ";");
                    jointMap[childFn.fullPathName].RotateTranslation(jointOrient);
                }

                processedJoints.Add(jointPath.fullPathName);
            }
            return(jointMap);
        }