Beispiel #1
0
        public static Dictionary <string, List <object> > getParticles(string name, bool unitizeVelocity = false)
        {
            MDoubleArray pPos = new MDoubleArray();

            MGlobal.executeCommand("getParticleAttr -at position -at velocity -array true " + name, pPos);
            List <object> particlePos = new List <object>();
            List <object> particleVec = new List <object>();
            int           numPart     = 0;


            var posAttr = DMInterop.getPlug(name, "position");

            if (posAttr.isArray)
            {
                numPart     = (int)posAttr.numElements;
                particlePos = new List <object>(numPart);
                particleVec = new List <object>(numPart);

                for (uint i = 0; i < numPart; i += 3)
                {
                    particlePos.Add(Point.ByCoordinates(posAttr[i].asDouble(), posAttr[i + 1].asDouble(), posAttr[i + 2].asDouble()));
                }
            }

            return(new Dictionary <string, List <object> >
            {
                { "Particles", particlePos },
                { "Velocity", particleVec }
            });
        }
        public void receiveCurveFromMaya(string node_name, out Point3DCollection controlVertices, out List<double> weights, out List<double> knots, out int degree, out bool closed, out bool rational)
        {
            MPlug plLocal = getPlug(node_name, "local");
            MObject oLocal = new MObject();
            plLocal.getValue(oLocal);

            MFnNurbsCurve nc = new MFnNurbsCurve(oLocal);

            MPointArray p_aCVs = new MPointArray();
            nc.getCVs(p_aCVs, MSpace.Space.kWorld);
            controlVertices = new Point3DCollection();
            weights = new List<double>();
            foreach (MPoint p in p_aCVs)
            {
                controlVertices.Add(new Point3D(p.x, p.y, p.z));
                weights.Add(1.0);
            }

            double min = 0, max = 0;
            nc.getKnotDomain(ref min, ref max);
            MDoubleArray d_aKnots = new MDoubleArray();
            nc.getKnots(d_aKnots);

            knots = new List<double>();
            knots.Add(min);
            foreach (double d in d_aKnots)
            {
                knots.Add(d);
            }
            knots.Add(max);

            degree = nc.degree;
            closed = nc.form == MFnNurbsCurve.Form.kClosed ? true : false;
            rational = true;
        }
Beispiel #3
0
        /// <summary>
        /// Get for each vertex the weights for all influence objects, including zero weights.
        /// </summary>
        /// <param name="vertexWeights"></param>
        /// <param name="influenceObjects"></param>
        /// <param name="meshPath"></param>
        private static void GetMeshWeightData(List <MDoubleArray> vertexWeights, MDagPathArray influenceObjects, MDagPath meshPath)
        {
            var fnMesh = new MFnMesh(meshPath);

            // Get any attached skin cluster
            var hasSkinCluster = false;

            // Search the skin cluster affecting this geometry
            var kDepNodeIt = new MItDependencyNodes(MFn.Type.kSkinClusterFilter);

            // Go through each skin cluster in the scene until we find the one connected to this mesh
            while (!kDepNodeIt.isDone && !hasSkinCluster)
            {
                MGlobal.displayInfo("Processing skin cluster...");
                var kObject         = kDepNodeIt.thisNode;
                var kSkinClusterFn  = new MFnSkinCluster(kObject);
                var uiNumGeometries = kSkinClusterFn.numOutputConnections;
                kSkinClusterFn.influenceObjects(influenceObjects);
                MGlobal.displayInfo("\t uiNumGeometries : " + uiNumGeometries);
                MGlobal.displayInfo("\t influenceOBjects number : " + influenceObjects.Count);

                // Go through each connection on the skin cluster until we get the one connecting to this mesh
                MGlobal.displayInfo("Mesh we are looking for : " + fnMesh.fullPathName);
                for (uint uiGeometry = 0; uiGeometry < uiNumGeometries && !hasSkinCluster; uiGeometry++)
                {
                    var uiIndex       = kSkinClusterFn.indexForOutputConnection(uiGeometry);
                    var kInputObject  = kSkinClusterFn.inputShapeAtIndex(uiIndex);
                    var kOutputObject = kSkinClusterFn.outputShapeAtIndex(uiIndex);
                    if (!kOutputObject.hasFn(MFn.Type.kMesh))
                    {
                        continue;
                    }
                    var fnOutput = new MFnMesh(MDagPath.getAPathTo(kOutputObject));
                    MGlobal.displayInfo("Output object : " + fnOutput.fullPathName);

                    if (fnOutput.fullPathName != fnMesh.fullPathName)
                    {
                        continue;
                    }

                    hasSkinCluster = true;
                    MGlobal.displayInfo("\t==> A connected skin cluster has been found.");

                    // Go through each vertex (== each component) and save the weights for each one
                    var kGeometryIt = new MItGeometry(kInputObject);
                    while (!kGeometryIt.isDone)
                    {
                        var  kComponent      = kGeometryIt.currentItem;
                        var  kWeightArray    = new MDoubleArray();
                        uint uiNumInfluences = 0;
                        kSkinClusterFn.getWeights(meshPath, kComponent, kWeightArray, ref uiNumInfluences);
                        vertexWeights.Add(kWeightArray);

                        kGeometryIt.next();
                    }
                }
                kDepNodeIt.next();
            }
        }
        public static double[] GetKnotsU(MFnNurbsSurface mayaSurface)
        {
            MDoubleArray knotU = new MDoubleArray();

            mayaSurface.getKnotsInU(knotU);

            return(knotU.ToArray());
        }
        public static double[] GetKnotsV(MFnNurbsSurface mayaSurface)
        {
            MDoubleArray knotV = new MDoubleArray();

            mayaSurface.getKnotsInV(knotV);

            return(knotV.ToArray());
        }
Beispiel #6
0
        private MMatrix GetMMatrix(MFnTransform mFnTransform, double currentFrame = 0)
        {
            // get transformation matrix at this frame
            MDoubleArray mDoubleMatrix = new MDoubleArray();

            MGlobal.executeCommand($"getAttr -t {currentFrame} {mFnTransform.fullPathName}.matrix", mDoubleMatrix);
            mDoubleMatrix.get(out float[] localMatrix);

            return(new MMatrix(localMatrix));
        }
Beispiel #7
0
        internal static Surface mNurbsSurfaceToDynamoSurface(MFnNurbsSurface surface, MSpace.Space space)
        {
            MPointArray cvs = new MPointArray();

            surface.getCVs(cvs, space);

            MDoubleArray knotU = new MDoubleArray();
            MDoubleArray knotV = new MDoubleArray();


            surface.getKnotsInU(knotU);
            surface.getKnotsInV(knotV);
            double Us = knotU[0], Ue = knotU[knotU.Count - 1], Vs = knotV[0], Ve = knotV[knotV.Count - 1];

            //surface.getKnotDomain(ref Us, ref Ue, ref Vs, ref Ve);

            knotU.insert(Us, 0);
            knotU.Add(Ue);
            knotV.insert(Vs, 0);
            knotV.Add(Ve);

            int cvUct = surface.numCVsInU;
            int cvVct = surface.numCVsInV;

            int uDeg = surface.degreeU;
            int vDeg = surface.degreeV;

            Point[][]  ctrlPts = new Point[cvUct][];
            double[][] weights = new double[cvUct][];

            for (int i = 0; i < cvUct; i++)
            {
                ctrlPts[i] = new Point[cvVct];
                weights[i] = new double[cvVct];

                for (int j = 0; j < cvVct; j++)
                {
                    weights[i][j] = 1;
                    if (MGlobal.isZAxisUp)
                    {
                        ctrlPts[i][j] = Point.ByCoordinates(cvs[(i * cvVct) + j].x, cvs[(i * cvVct) + j].y, cvs[(i * cvVct) + j].z);
                    }
                    else
                    {
                        ctrlPts[i][j] = Point.ByCoordinates(cvs[(i * cvVct) + j].x, -cvs[(i * cvVct) + j].z, cvs[(i * cvVct) + j].y);
                    }
                }
            }

            //Surface result = NurbsSurface.ByControlPoints(ctrlPts, uDeg, vDeg);
            Surface result = NurbsSurface.ByControlPointsWeightsKnots(ctrlPts, weights, knotU.ToArray(), knotV.ToArray(), uDeg, vDeg);

            return(result);
        }
Beispiel #8
0
        public void sendCurveToMaya(string node_name, Point3DCollection controlVertices, List <double> knots, int degree,
                                    MFnNurbsCurveForm form)
        {
            var dn             = new MFnDagNode(getDagNode(node_name));
            var plCreate       = dn.findPlug("create");
            var plDynamoCreate = new MPlug();

            try
            {
                plDynamoCreate = dn.findPlug("dynamoCreate");
            }
            catch
            {
                var tAttr           = new MFnTypedAttribute();
                var ldaDynamoCreate = tAttr.create("dynamoCreate", "dc", MFnData.Type.kNurbsCurve, MObject.kNullObj);
                try
                {
                    dn.addAttribute(ldaDynamoCreate, MFnDependencyNode.MAttrClass.kLocalDynamicAttr);
                    plDynamoCreate = dn.findPlug(ldaDynamoCreate);
                    var dagm = new MDagModifier();
                    dagm.connect(plDynamoCreate, plCreate);
                    dagm.doIt();
                }
                catch
                {
                    return;
                }
            }

            var ncd    = new MFnNurbsCurveData();
            var oOwner = ncd.create();
            var nc     = new MFnNurbsCurve();

            var p_aControlVertices = new MPointArray();

            foreach (var p in controlVertices)
            {
                p_aControlVertices.Add(new MPoint(p.X, p.Y, p.Z));
            }

            var d_aKnots = new MDoubleArray();

            for (var i = 1; i < knots.Count - 1; ++i)
            {
                d_aKnots.Add(knots[i]);
            }

            nc.create(p_aControlVertices, d_aKnots, (uint)degree, (MFnNurbsCurve.Form)form, false, true, oOwner);

            plDynamoCreate.setMObject(oOwner);

            MGlobal.executeCommandOnIdle(string.Format("dgdirty {0}.create;", node_name));
        }
Beispiel #9
0
        public static List <object> MelCommand(string MelCommand)
        {
            MStringArray   stringResults = new MStringArray();
            MIntArray      intResults    = new MIntArray();
            MDoubleArray   doubleResults = new MDoubleArray();
            MVectorArray   vectorResults = new MVectorArray();
            List <object>  results       = new List <object>();
            MCommandResult mcr           = new MCommandResult();


            MDagPath dag = new MDagPath();

            try
            {
                MGlobal.executeCommand(MelCommand, mcr);
                //   MGlobal.executeCommand(MelCommand, stringResults);
            }
            catch (MemberAccessException e)
            {
                MGlobal.displayWarning(e.Message);
            }

            switch (mcr.resultType)
            {
            case MCommandResult.Type.kStringArray:
                mcr.getResult(stringResults);
                results.AddRange(stringResults);
                break;

            case MCommandResult.Type.kIntArray:
                mcr.getResult(intResults);
                results.AddRange(intResults.Cast <object>());
                break;

            case MCommandResult.Type.kDoubleArray:
                mcr.getResult(doubleResults);
                results.AddRange(doubleResults.Cast <object>());
                break;

            case MCommandResult.Type.kVectorArray:
                mcr.getResult(vectorResults);
                results.AddRange(vectorResults.Cast <object>());
                break;

            default:
                mcr.getResult(stringResults);
                results.AddRange(stringResults);
                break;
            }
            mcr.Dispose();
            return(results);
        }
        public override void readDoubleArray(MDoubleArray array, uint size)
        {
            Trace.Assert(myCurrentChanelNode != null);

            XmlNode     doubleArrayNode = myCurrentChanelNode.SelectSingleNode(doubleArrayTag);
            XmlNodeList valueNodeList   = doubleArrayNode.SelectNodes("value");

            array.clear();
            array.length = size;
            foreach (XmlNode valueNode in valueNodeList)
            {
                double value = Convert.ToDouble(valueNode.InnerText);
                array.append(value);
            }
            return;
        }
Beispiel #11
0
        public static MDagPath CreateCurve(MPointArray points, string curveName, int degree = 1, MFnNurbsCurve.Form form = MFnNurbsCurve.Form.kOpen)
        {
            MDoubleArray indices = new MDoubleArray();

            for (int i = 0; i < points.Count; i++)
            {
                indices.Add(i);
            }

            MFnNurbsCurve     nc           = new MFnNurbsCurve();
            MObject           curveObject  = nc.create(points, indices, (uint)degree, form, false, false);
            MDagPath          curveDagPath = MDagPath.getAPathTo(curveObject);
            MFnDependencyNode dn           = new MFnDependencyNode(curveObject);

            dn.setName(curveName);
            return(curveDagPath);
        }
Beispiel #12
0
        /// <summary>
        /// Check if the nodes have a scale near to zero.
        /// </summary>
        /// <param name="nodes"></param>
        /// <param name="currentFrame"></param>
        /// <returns>
        /// True if all nodes have a scale higher than zero + epsilon
        /// Flase otherwise
        /// </returns>
        private bool HasNonZeroScale(List <MObject> nodes, double currentFrame)
        {
            bool isValid = true;

            for (int index = 0; index < nodes.Count && isValid; index++)
            {
                MObject      node      = nodes[index];
                MFnTransform transform = new MFnTransform(node);

                // get scale at this frame
                MDoubleArray mDoubleScale = new MDoubleArray();
                MGlobal.executeCommand($"getAttr -t {currentFrame.ToString(System.Globalization.CultureInfo.InvariantCulture)} {transform.fullPathName}.scale", mDoubleScale);
                mDoubleScale.get(out float[] scale);

                isValid = !scale.IsEqualTo(new float[] { 0, 0, 0 }, 0.01f);
            }

            return(isValid);
        }
Beispiel #13
0
        /// <summary>
        /// Return the max influence of a skin cluster on a mesh.
        /// </summary>
        /// <param name="skin">the skin</param>
        /// <param name="transform">the transform above the mesh</param>
        /// <param name="mesh">the mesh</param>
        /// <returns>The max influence</returns>
        private int GetMaxInfluence(MFnSkinCluster skin, MFnTransform transform, MFnMesh mesh)
        {
            int maxNumInfluences = 0;
            int numVertices      = mesh.numVertices;

            // Get max influence on a vertex
            for (int index = 0; index < numVertices; index++)
            {
                MDoubleArray influenceWeights = new MDoubleArray();
                String       command          = $"skinPercent -query -value {skin.name} {transform.name}.vtx[{index}]";
                // Get the weight values of all the influences for this vertex
                MGlobal.executeCommand(command, influenceWeights);

                int numInfluences = influenceWeights.Count(weight => weight != 0);

                maxNumInfluences = Math.Max(maxNumInfluences, numInfluences);
            }

            return(maxNumInfluences);
        }
Beispiel #14
0
        public static Point getObjectCenter(string ObjName)
        {
            MDoubleArray results = new MDoubleArray();

            Task waitForCompletion = Task.Factory.StartNew(() => MGlobal.executeCommand("objectCenter -gl " + ObjName, results));

            waitForCompletion.Wait(5000);
            Point center;

            if (MGlobal.isZAxisUp)
            {
                center = Point.ByCoordinates(results[0], results[1], results[2]);
            }
            else
            {
                center = Point.ByCoordinates(results[0], results[2], -results[1]);
            }

            return(center);
        }
Beispiel #15
0
        /// <summary>
        /// Find the keyframe of the blend shape and store the morph target and its weights in the map.
        /// </summary>
        /// <param name="blendShapeDeformerName"></param>
        /// <returns>A map with the morph target (Maya object) as key and its weights as value</returns>
        private IDictionary <double, IList <double> > GetMorphWeightsByFrame(string blendShapeDeformerName)
        {
            Dictionary <double, IList <double> > weights = new Dictionary <double, IList <double> >();

            IList <double> keys = GetKeyframes(blendShapeDeformerName);

            for (int index = 0; index < keys.Count; index++)
            {
                double key = keys[index];

                // Get the envelope
                MGlobal.executeCommand($"getAttr -t {key.ToString(System.Globalization.CultureInfo.InvariantCulture)} {blendShapeDeformerName}.envelope", out double envelope);

                // Get the weight at this keyframe
                MDoubleArray weightArray = new MDoubleArray();
                MGlobal.executeCommand($"getAttr -t {key.ToString(System.Globalization.CultureInfo.InvariantCulture)} {blendShapeDeformerName}.weight", weightArray);

                weights[key] = weightArray.Select(weight => envelope * weight).ToList();
            }

            return(weights);
        }
        public override void writeDoubleArray(MDoubleArray array)
        {
            if (myCurrentChanelNode != null)
            {
                uint    size     = array.length;
                XmlNode sizeNode = myXmlDoc.CreateElement(sizeTag);
                sizeNode.InnerText = Convert.ToString(size);
                myCurrentChanelNode.AppendChild(sizeNode);

                XmlNode arrayNode = myXmlDoc.CreateElement(doubleArrayTag);
                myCurrentChanelNode.AppendChild(arrayNode);

                for (int i = 0; i < size; i++)
                {
                    string  value     = array[i].ToString();
                    XmlNode valueNode = myXmlDoc.CreateElement("value");
                    arrayNode.AppendChild(valueNode);
                }
            }

            return;
        }
Beispiel #17
0
        public void receiveCurveFromMaya(string node_name, out Point3DCollection controlVertices, out List <double> weights, out List <double> knots, out int degree, out bool closed, out bool rational)
        {
            MPlug   plLocal = getPlug(node_name, "local");
            MObject oLocal  = new MObject();

            plLocal.getValue(oLocal);

            MFnNurbsCurve nc = new MFnNurbsCurve(oLocal);

            MPointArray p_aCVs = new MPointArray();

            nc.getCVs(p_aCVs, MSpace.Space.kWorld);
            controlVertices = new Point3DCollection();
            weights         = new List <double>();
            foreach (MPoint p in p_aCVs)
            {
                controlVertices.Add(new Point3D(p.x, p.y, p.z));
                weights.Add(1.0);
            }

            double min = 0, max = 0;

            nc.getKnotDomain(ref min, ref max);
            MDoubleArray d_aKnots = new MDoubleArray();

            nc.getKnots(d_aKnots);

            knots = new List <double>();
            knots.Add(min);
            foreach (double d in d_aKnots)
            {
                knots.Add(d);
            }
            knots.Add(max);

            degree   = nc.degree;
            closed   = nc.form == MFnNurbsCurve.Form.kClosed ? true : false;
            rational = true;
        }
Beispiel #18
0
        /// <summary>
        /// Using the Maya object name, find its keyframe.
        /// </summary>
        /// <param name="objectName"></param>
        /// <returns>A sorted list of keyframe without duplication. This list contains at least the first and last key of the time range.</returns>
        public IList <double> GetKeyframes(string objectName)
        {
            IList <double> keys = new List <double>();

            int start = Loader.GetMinTime();
            int end   = Loader.GetMaxTime();

            // Get the keyframe
            try
            {
                MDoubleArray keyArray = new MDoubleArray();
                MGlobal.executeCommand($"keyframe -t \":\" -q -timeChange {objectName}", keyArray);

                keyArray.Add(start);
                keyArray.Add(end);

                SortedSet <double> sortedKeys = new SortedSet <double>(keyArray);
                keys = new List <double>(sortedKeys);
            }
            catch { }

            return(keys);
        }
        public override void readDoubleArray(MDoubleArray array, uint size)
        {
            Trace.Assert(myCurrentChanelNode != null);

            XmlNode doubleArrayNode = myCurrentChanelNode.SelectSingleNode(doubleArrayTag);
            XmlNodeList valueNodeList = doubleArrayNode.SelectNodes("value");
            array.clear();
            array.length = size;
            foreach (XmlNode valueNode in valueNodeList)
            {
                double value = Convert.ToDouble(valueNode.InnerText);
                array.append(value);
            }
            return;
        }
Beispiel #20
0
        public static void ToMaya(Surface SurfaceToSend, string name, string groupName)
        {
            NurbsSurface dynSurf;

            try
            {
                dynSurf = SurfaceToSend.ToNurbsSurface();
            }
            catch (Exception)
            {
                dynSurf = null;
                MGlobal.displayWarning("Surface has no nurbSurface form");
            }

            //MFnNurbsSurface updatedSurface;
            MPointArray cvs = new MPointArray();

            Point[][] ctrlPts = dynSurf.ControlPoints();

            for (int i = 0; i < ctrlPts.Length; i++)
            {
                for (int j = 0; j < ctrlPts[i].Length; j++)
                {
                    MPoint p = new MPoint();
                    if (MGlobal.isZAxisUp)
                    {
                        p.x = ctrlPts[i][j].X;
                        p.y = ctrlPts[i][j].Y;
                        p.z = ctrlPts[i][j].Z;
                    }
                    else
                    {
                        p.x = ctrlPts[i][j].X;
                        p.y = ctrlPts[i][j].Z;
                        p.z = -ctrlPts[i][j].Y;
                    }


                    cvs.Add(p);
                }
            }
            MDoubleArray uknot = new MDoubleArray(dynSurf.UKnots());

            uknot.RemoveAt(0);
            uknot.RemoveAt(uknot.Count - 1);
            MDoubleArray vknot = new MDoubleArray(dynSurf.VKnots());

            vknot.RemoveAt(0);
            vknot.RemoveAt(vknot.Count - 1);

            MFnNurbsSurface.Form formU = MFnNurbsSurface.Form.kInvalid;
            MFnNurbsSurface.Form formV = MFnNurbsSurface.Form.kInvalid;

            if (dynSurf.IsPeriodicInU)
            {
                formU = MFnNurbsSurface.Form.kPeriodic;
            }
            else if (dynSurf.ClosedInU)
            {
                formU = MFnNurbsSurface.Form.kClosed;
            }
            else
            {
                formU = MFnNurbsSurface.Form.kOpen;
            }

            if (dynSurf.IsPeriodicInV)
            {
                formV = MFnNurbsSurface.Form.kPeriodic;
            }
            else if (dynSurf.ClosedInV)
            {
                formV = MFnNurbsSurface.Form.kClosed;
            }
            else
            {
                formV = MFnNurbsSurface.Form.kOpen;
            }

            MDagPath existingDagPath = null;
            bool     nodeExists      = false;

            //trims
            //toDo: impement trims


            Task checkNode = null;



            try
            {
                checkNode = Task.Factory.StartNew(() => existingDagPath = DMInterop.getDagNode(name));
                checkNode.Wait(500);

                nodeExists = true;
            }
            catch (Exception)
            {
                nodeExists = false;
            }

            MObject obj;

            if (nodeExists)
            {
                if (checkNode.IsCompleted)
                {
                    MFnNurbsSurface existingSurface = new MFnNurbsSurface(existingDagPath);
                    MDGModifier     mdgModifier     = new MDGModifier();



                    // if (existingSurface.degreeU == dynSurf.DegreeU && existingSurface.degreeV== dynSurf.DegreeV && existingSurface.numCVsInU == ctrlPts.Length && existingSurface.numCVsInV == ctrlPts[0].Length )
                    //{

                    if (existingSurface.degreeU != dynSurf.DegreeU || existingSurface.degreeV != dynSurf.DegreeV || existingSurface.numCVsInU != ctrlPts.Length || existingSurface.numCVsInV != ctrlPts[0].Length)
                    {
                        //this is a hack to rebuild the surface. proper way is to make new surface and assign as input to aold surface
                        MGlobal.executeCommand(string.Format("rebuildSurface -du {0} -dv {1} -su {2} -sv {3} {4}", dynSurf.DegreeU, dynSurf.DegreeV, ctrlPts.Length - 3, ctrlPts[0].Length - 3, name));
                    }
                    //  updatedSurface = existingSurface;
                    existingSurface.setCVs(cvs);
                    existingSurface.setKnotsInU(uknot, 0, (uint)existingSurface.numKnotsInU - 1);
                    existingSurface.setKnotsInV(vknot, 0, (uint)existingSurface.numKnotsInV - 1);
                    existingSurface.updateSurface();


                    // }

                    /*
                     * else
                     *
                     * {
                     * //get all the existing node types
                     * MFnDagNode dagNodeExist = new MFnDagNode(existingDagPath);
                     * MObject existSurfObj = existingDagPath.node;
                     * MFnDependencyNode depNodeExist = new MFnDependencyNode(existSurfObj);
                     *
                     *
                     * updatedSurface = new MFnNurbsSurface();
                     * var newSurfObj = dagNodeExist.duplicate();
                     * updatedSurface.isIntermediateObject = true;
                     *
                     * updatedSurface.create(cvs, uknot, vknot, (uint)dynSurf.DegreeU, (uint)dynSurf.DegreeV, formU, formV, dynSurf.IsRational, newSurfObj);
                     * MFnDependencyNode depNodeNew = new MFnDependencyNode(newSurfObj);
                     *
                     * MPlug outSurf = depNodeExist.findPlug("outputSurface");
                     * MPlug inSurf = depNodeNew.findPlug("inputSurface");
                     *
                     *
                     * mdgModifier.connect(outSurf, inSurf);
                     *
                     *
                     * }
                     */
                    mdgModifier.doIt();

                    // MFnDependencyNode nodeFn = new MFnDagNode(mSurf);
                    //nodeFn.setName(name);
                    //MGlobal.executeCommand("sets -e -forceElement initialShadingGroup " + nodeFn.name);
                }
            }
            else
            {
                if (checkNode.IsCompleted)
                {
                    MFnNurbsSurface updatedSurface = new MFnNurbsSurface();
                    obj = updatedSurface.create(cvs, uknot, vknot, (uint)dynSurf.DegreeU, (uint)dynSurf.DegreeV, formU, formV, dynSurf.IsRational);
                    MFnDependencyNode nodeFn = new MFnDagNode(obj);

                    nodeFn.setName(name);
                    MGlobal.executeCommand("sets -e -forceElement initialShadingGroup " + nodeFn.name);
                }
            }

            if (groupName != "")
            {
                bool groupExists = false;
                try
                {
                    DMInterop.getDagNode(groupName);
                    groupExists = true;
                }
                catch { }

                if (groupExists)
                {
                    MGlobal.executeCommand(string.Format("parent {0} {1}", groupName, name));
                }
                else
                {
                    MGlobal.executeCommand(string.Format("group -n {0} {1}", groupName, name));
                }
            }
        }
        public override void doIt(MArgList args)
        {
            // parse args to get the file name from the command-line
            //
            parseArgs(args);
            uint count = 0;


            // Iterate through graph and search for skinCluster nodes
            //
            MItDependencyNodes iter = new MItDependencyNodes(MFn.Type.kInvalid);

            for ( ; !iter.isDone; iter.next())
            {
                MObject obj = iter.item;
                if (obj.apiType == MFn.Type.kSkinClusterFilter)
                {
                    count++;

                    // For each skinCluster node, get the list of influence objects
                    //
                    MFnSkinCluster skinCluster = new MFnSkinCluster(obj);
                    MDagPathArray  infs        = new MDagPathArray();
                    uint           nInfs;
                    try
                    {
                        nInfs = skinCluster.influenceObjects(infs);
                    }
                    catch (Exception)
                    {
                        MGlobal.displayInfo("Error getting influence objects.");
                        continue;
                    }
                    if (0 == nInfs)
                    {
                        MGlobal.displayInfo("Error: No influence objects found.");
                        continue;
                    }

                    // loop through the geometries affected by this cluster
                    //
                    uint nGeoms = skinCluster.numOutputConnections;
                    for (uint ii = 0; ii < nGeoms; ++ii)
                    {
                        uint index;
                        try
                        {
                            index = skinCluster.indexForOutputConnection(ii);
                        }
                        catch (Exception)
                        {
                            MGlobal.displayInfo("Error getting geometry index.");
                            continue;
                        }

                        // get the dag path of the ii'th geometry
                        //
                        MDagPath skinPath = new MDagPath();
                        try{
                            skinCluster.getPathAtIndex(index, skinPath);
                        }
                        catch (Exception)
                        {
                            MGlobal.displayInfo("Error getting geometry path.");
                            continue;
                        }

                        // iterate through the components of this geometry
                        //
                        MItGeometry gIter = new MItGeometry(skinPath);

                        // print out the path name of the skin, vertexCount & influenceCount
                        //
                        UnicodeEncoding uniEncoding = new UnicodeEncoding();
                        string          res         = String.Format("{0} {1} {2}\n", skinPath.partialPathName, gIter.count, nInfs);
                        file.Write(uniEncoding.GetBytes(res), 0, uniEncoding.GetByteCount(res));

                        // print out the influence objects
                        //
                        for (int kk = 0; kk < nInfs; ++kk)
                        {
                            res = String.Format("{0} ", infs[kk].partialPathName);
                            file.Write(uniEncoding.GetBytes(res), 0, uniEncoding.GetByteCount(res));
                        }
                        res = "\n";
                        file.Write(uniEncoding.GetBytes(res), 0, uniEncoding.GetByteCount(res));

                        for (/* nothing */; !gIter.isDone; gIter.next())
                        {
                            MObject comp;
                            try
                            {
                                comp = gIter.component;
                            }
                            catch (Exception)
                            {
                                MGlobal.displayInfo("Error getting geometry path.");
                                continue;
                            }


                            // Get the weights for this vertex (one per influence object)
                            //
                            MDoubleArray wts      = new MDoubleArray();
                            uint         infCount = 0;
                            try
                            {
                                skinCluster.getWeights(skinPath, comp, wts, ref infCount);
                            }
                            catch (Exception)
                            {
                                displayError("Error getting weights.");
                                continue;
                            }
                            if (0 == infCount)
                            {
                                displayError("Error: 0 influence objects.");
                            }

                            // Output the weight data for this vertex
                            //
                            res = String.Format("{0} ", gIter.index);
                            file.Write(uniEncoding.GetBytes(res), 0, uniEncoding.GetByteCount(res));
                            for (int jj = 0; jj < infCount; ++jj)
                            {
                                res = String.Format("{0} ", wts[jj]);
                                file.Write(uniEncoding.GetBytes(res), 0, uniEncoding.GetByteCount(res));
                            }
                            file.Write(uniEncoding.GetBytes("\n"), 0, uniEncoding.GetByteCount("\n"));
                        }
                    }
                }
            }

            if (0 == count)
            {
                displayError("No skinClusters found in this scene.");
            }
            file.Close();
            return;
        }
Beispiel #22
0
        /// <summary>
        /// Extract geometry (position, normal, UVs...) for a specific vertex
        /// </summary>
        /// <param name="mFnMesh"></param>
        /// <param name="polygonId">The polygon (face) to examine</param>
        /// <param name="vertexIndexGlobal">The object-relative (mesh-relative/global) vertex index</param>
        /// <param name="vertexIndexLocal">The face-relative (local) vertex id to examine</param>
        /// <param name="uvSetNames"></param>
        /// <param name="isUVExportSuccess"></param>
        /// <returns></returns>
        private GlobalVertex ExtractVertex(MFnMesh mFnMesh, int polygonId, int vertexIndexGlobal, int vertexIndexLocal, MStringArray uvSetNames, ref bool[] isUVExportSuccess, ref bool isTangentExportSuccess)
        {
            MPoint point = new MPoint();

            mFnMesh.getPoint(vertexIndexGlobal, point);

            MVector normal = new MVector();

            mFnMesh.getFaceVertexNormal(polygonId, vertexIndexGlobal, normal);

            // Switch coordinate system at object level
            point.z  *= -1;
            normal.z *= -1;

            var vertex = new GlobalVertex
            {
                BaseIndex = vertexIndexGlobal,
                Position  = point.toArray(),
                Normal    = normal.toArray()
            };

            // Tangent
            if (isTangentExportSuccess)
            {
                try
                {
                    MVector tangent = new MVector();
                    mFnMesh.getFaceVertexTangent(polygonId, vertexIndexGlobal, tangent);

                    // Switch coordinate system at object level
                    tangent.z *= -1;

                    int  tangentId            = mFnMesh.getTangentId(polygonId, vertexIndexGlobal);
                    bool isRightHandedTangent = mFnMesh.isRightHandedTangent(tangentId);

                    // Invert W to switch to left handed system
                    vertex.Tangent = new float[] { (float)tangent.x, (float)tangent.y, (float)tangent.z, isRightHandedTangent ? -1 : 1 };
                }
                catch
                {
                    // Exception raised when mesh don't have tangents
                    isTangentExportSuccess = false;
                }
            }

            // Color
            int    colorIndex;
            string colorSetName;

            float[] defaultColor = new float[] { 1, 1, 1, 0 };
            MColor  color        = new MColor();

            mFnMesh.getCurrentColorSetName(out colorSetName);

            if (mFnMesh.numColors(colorSetName) > 0)
            {
                //Get the color index
                mFnMesh.getColorIndex(polygonId, vertexIndexLocal, out colorIndex);

                //if a color is set
                if (colorIndex != -1)
                {
                    mFnMesh.getColor(colorIndex, color);
                    vertex.Color = color.toArray();
                }
                //else set the default color
                else
                {
                    vertex.Color = defaultColor;
                }
            }

            // UV
            int indexUVSet = 0;

            if (uvSetNames.Count > indexUVSet && isUVExportSuccess[indexUVSet])
            {
                try
                {
                    float u = 0, v = 0;
                    mFnMesh.getPolygonUV(polygonId, vertexIndexLocal, ref u, ref v, uvSetNames[indexUVSet]);
                    vertex.UV = new float[] { u, v };
                }
                catch
                {
                    // An exception is raised when a vertex isn't mapped to an UV coordinate
                    isUVExportSuccess[indexUVSet] = false;
                }
            }
            indexUVSet = 1;
            if (uvSetNames.Count > indexUVSet && isUVExportSuccess[indexUVSet])
            {
                try
                {
                    float u = 0, v = 0;
                    mFnMesh.getPolygonUV(polygonId, vertexIndexLocal, ref u, ref v, uvSetNames[indexUVSet]);
                    vertex.UV2 = new float[] { u, v };
                }
                catch
                {
                    // An exception is raised when a vertex isn't mapped to an UV coordinate
                    isUVExportSuccess[indexUVSet] = false;
                }
            }

            // skin
            if (mFnSkinCluster != null)
            {
                // Filter null weights
                Dictionary <int, double> weightByInfluenceIndex = new Dictionary <int, double>(); // contains the influence indices with weight > 0

                // Export Weights and BonesIndices for the vertex
                // Get the weight values of all the influences for this vertex
                allMayaInfluenceWeights = new MDoubleArray();
                MGlobal.executeCommand($"skinPercent -query -value {mFnSkinCluster.name} {mFnTransform.name}.vtx[{vertexIndexGlobal}]",
                                       allMayaInfluenceWeights);
                allMayaInfluenceWeights.get(out double[] allInfluenceWeights);

                for (int influenceIndex = 0; influenceIndex < allInfluenceWeights.Length; influenceIndex++)
                {
                    double weight = allInfluenceWeights[influenceIndex];

                    if (weight > 0)
                    {
                        try
                        {
                            // add indice and weight in the local lists
                            weightByInfluenceIndex.Add(indexByNodeName[allMayaInfluenceNames[influenceIndex]], weight);
                        }
                        catch (Exception e)
                        {
                            RaiseError(e.Message, 2);
                            RaiseError(e.StackTrace, 3);
                        }
                    }
                }

                // normalize weights => Sum weights == 1
                Normalize(ref weightByInfluenceIndex);

                // decreasing sort
                OrderByDescending(ref weightByInfluenceIndex);

                int   bonesCount = indexByNodeName.Count; // number total of bones/influences for the mesh
                float weight0    = 0;
                float weight1    = 0;
                float weight2    = 0;
                float weight3    = 0;
                int   bone0      = bonesCount;
                int   bone1      = bonesCount;
                int   bone2      = bonesCount;
                int   bone3      = bonesCount;
                int   nbBones    = weightByInfluenceIndex.Count; // number of bones/influences for this vertex

                if (nbBones == 0)
                {
                    weight0 = 1.0f;
                    bone0   = bonesCount;
                }

                if (nbBones > 0)
                {
                    bone0   = weightByInfluenceIndex.ElementAt(0).Key;
                    weight0 = (float)weightByInfluenceIndex.ElementAt(0).Value;

                    if (nbBones > 1)
                    {
                        bone1   = weightByInfluenceIndex.ElementAt(1).Key;
                        weight1 = (float)weightByInfluenceIndex.ElementAt(1).Value;

                        if (nbBones > 2)
                        {
                            bone2   = weightByInfluenceIndex.ElementAt(2).Key;
                            weight2 = (float)weightByInfluenceIndex.ElementAt(2).Value;

                            if (nbBones > 3)
                            {
                                bone3   = weightByInfluenceIndex.ElementAt(3).Key;
                                weight3 = (float)weightByInfluenceIndex.ElementAt(3).Value;
                            }
                        }
                    }
                }

                float[] weights = { weight0, weight1, weight2, weight3 };
                vertex.Weights      = weights;
                vertex.BonesIndices = (bone3 << 24) | (bone2 << 16) | (bone1 << 8) | bone0;

                if (nbBones > 4)
                {
                    bone0   = weightByInfluenceIndex.ElementAt(4).Key;
                    weight0 = (float)weightByInfluenceIndex.ElementAt(4).Value;
                    weight1 = 0;
                    weight2 = 0;
                    weight3 = 0;

                    if (nbBones > 5)
                    {
                        bone1   = weightByInfluenceIndex.ElementAt(5).Key;
                        weight1 = (float)weightByInfluenceIndex.ElementAt(4).Value;

                        if (nbBones > 6)
                        {
                            bone2   = weightByInfluenceIndex.ElementAt(6).Key;
                            weight2 = (float)weightByInfluenceIndex.ElementAt(4).Value;

                            if (nbBones > 7)
                            {
                                bone3   = weightByInfluenceIndex.ElementAt(7).Key;
                                weight3 = (float)weightByInfluenceIndex.ElementAt(7).Value;
                            }
                        }
                    }

                    float[] weightsExtra = { weight0, weight1, weight2, weight3 };
                    vertex.WeightsExtra      = weightsExtra;
                    vertex.BonesIndicesExtra = (bone3 << 24) | (bone2 << 16) | (bone1 << 8) | bone0;
                }
            }
            return(vertex);
        }
        public void sendCurveToMaya(string node_name, Point3DCollection controlVertices, List<double> knots, int degree, MFnNurbsCurveForm form)
        {
            MFnDagNode dn = new MFnDagNode(getDagNode(node_name));
            MPlug plCreate = dn.findPlug("create");
            MPlug plDynamoCreate = new MPlug();

            try
            {
                plDynamoCreate = dn.findPlug("dynamoCreate");
            }
            catch
            {
                MFnTypedAttribute tAttr = new MFnTypedAttribute();
                MObject ldaDynamoCreate = tAttr.create("dynamoCreate", "dc", MFnData.Type.kNurbsCurve, MObject.kNullObj);
                try
                {
                    dn.addAttribute(ldaDynamoCreate, MFnDependencyNode.MAttrClass.kLocalDynamicAttr);
                    plDynamoCreate = dn.findPlug(ldaDynamoCreate);
                    MDagModifier dagm = new MDagModifier();
                    dagm.connect(plDynamoCreate, plCreate);
                    dagm.doIt();
                }
                catch
                {
                    return;
                }
            }

            MFnNurbsCurveData ncd = new MFnNurbsCurveData();
            MObject oOwner = ncd.create();
            MFnNurbsCurve nc = new MFnNurbsCurve();

            MPointArray p_aControlVertices = new MPointArray();
            foreach (Point3D p in controlVertices)
            {
                p_aControlVertices.Add(new MPoint(p.X, p.Y, p.Z));
            }

            MDoubleArray d_aKnots = new MDoubleArray();
            for (int i = 1; i < knots.Count - 1; ++i )
            {
                d_aKnots.Add(knots[i]);
            }

            nc.create(p_aControlVertices, d_aKnots, (uint)degree, (MFnNurbsCurve.Form)form, false, true, oOwner);

            plDynamoCreate.setMObject(oOwner);

            MGlobal.executeCommandOnIdle(String.Format("dgdirty {0}.create;", node_name));
        }
Beispiel #24
0
        public void receiveCurveFromMaya(string nodeName, int space, out Point3DCollection controlVertices,
                                         out List <double> weights, out List <double> knots, out int degree, out bool closed, out bool rational)
        {
            var dagnode = getDagNode(nodeName);
            var nc      = new MFnNurbsCurve(dagnode);

            var p_aCVs = new MPointArray();

            switch (space)
            {
            case 0:     //object
                nc.getCVs(p_aCVs, MSpace.Space.kObject);
                break;

            case 1:     //world
                nc.getCVs(p_aCVs, MSpace.Space.kWorld);
                break;

            default:
                nc.getCVs(p_aCVs, MSpace.Space.kWorld);
                break;
            }


            controlVertices = new Point3DCollection();
            weights         = new List <double>();
            if (MGlobal.isZAxisUp)
            {
                foreach (var p in p_aCVs)
                {
                    controlVertices.Add(new Point3D(p.x, p.y, p.z));
                    weights.Add(1.0);
                }
            }
            else
            {
                foreach (var p in p_aCVs)
                {
                    controlVertices.Add(new Point3D(p.x, -p.z, p.y));
                    weights.Add(1.0);
                }
            }

            double min = 0, max = 0;

            nc.getKnotDomain(ref min, ref max);
            var d_aKnots = new MDoubleArray();

            nc.getKnots(d_aKnots);

            knots = new List <double>();
            knots.Add(min);
            foreach (var d in d_aKnots)
            {
                knots.Add(d);
            }
            knots.Add(max);

            degree   = nc.degree;
            closed   = nc.form == MFnNurbsCurve.Form.kClosed ? true : false;
            rational = true;
        }
        public void Load(string name, SKLFile skl = null)
        {
            MIntArray        polygonIndexCounts = new MIntArray((uint)this.Indices.Count / 3);
            MIntArray        polygonIndices     = new MIntArray((uint)this.Indices.Count);
            MFloatPointArray vertices           = new MFloatPointArray((uint)this.Vertices.Count);
            MFloatArray      arrayU             = new MFloatArray((uint)this.Vertices.Count);
            MFloatArray      arrayV             = new MFloatArray((uint)this.Vertices.Count);
            MVectorArray     normals            = new MVectorArray((uint)this.Vertices.Count);
            MIntArray        normalIndices      = new MIntArray((uint)this.Vertices.Count);
            MFnMesh          mesh        = new MFnMesh();
            MDagPath         meshDagPath = new MDagPath();
            MDGModifier      modifier    = new MDGModifier();
            MFnSet           set         = new MFnSet();

            for (int i = 0; i < this.Indices.Count / 3; i++)
            {
                polygonIndexCounts[i] = 3;
            }

            for (int i = 0; i < this.Indices.Count; i++)
            {
                polygonIndices[i] = this.Indices[i];
            }

            for (int i = 0; i < this.Vertices.Count; i++)
            {
                SKNVertex vertex = this.Vertices[i];

                vertices[i]      = new MFloatPoint(vertex.Position.X, vertex.Position.Y, vertex.Position.Z);
                arrayU[i]        = vertex.UV.X;
                arrayV[i]        = 1 - vertex.UV.Y;
                normals[i]       = new MVector(vertex.Normal.X, vertex.Normal.Y, vertex.Normal.Z);
                normalIndices[i] = i;
            }

            //Assign mesh data
            mesh.create(this.Vertices.Count, this.Indices.Count / 3, vertices, polygonIndexCounts, polygonIndices, arrayU, arrayV, MObject.kNullObj);
            mesh.setVertexNormals(normals, normalIndices);
            mesh.getPath(meshDagPath);
            mesh.assignUVs(polygonIndexCounts, polygonIndices);

            //Set names
            mesh.setName(name);
            MFnTransform transformNode = new MFnTransform(mesh.parent(0));

            transformNode.setName("transform_" + name);

            //Get render partition
            MGlobal.displayInfo("SKNFile:Load - Searching for Render Partition");
            MItDependencyNodes itDependencyNodes = new MItDependencyNodes(MFn.Type.kPartition);
            MFnPartition       renderPartition   = new MFnPartition();
            bool foundRenderPartition            = false;

            for (; !itDependencyNodes.isDone; itDependencyNodes.next())
            {
                renderPartition.setObject(itDependencyNodes.thisNode);
                MGlobal.displayInfo("SKNFile:Load - Iterating through partition: " + renderPartition.name + " IsRenderPartition: " + renderPartition.isRenderPartition);
                if (renderPartition.name == "renderPartition" && renderPartition.isRenderPartition)
                {
                    MGlobal.displayInfo("SKNFile:Load - Found render partition");
                    foundRenderPartition = true;
                    break;
                }
            }


            //Create Materials
            for (int i = 0; i < this.Submeshes.Count; i++)
            {
                MFnDependencyNode dependencyNode = new MFnDependencyNode();
                MFnLambertShader  lambertShader  = new MFnLambertShader();
                SKNSubmesh        submesh        = this.Submeshes[i];
                MObject           shader         = lambertShader.create(true);

                lambertShader.setName(submesh.Name);
                lambertShader.color = MaterialProvider.GetMayaColor(i);

                MObject shadingEngine = dependencyNode.create("shadingEngine", submesh.Name + "_SG");
                MObject materialInfo  = dependencyNode.create("materialInfo", submesh.Name + "_MaterialInfo");
                if (foundRenderPartition)
                {
                    MPlug partitionPlug = new MFnDependencyNode(shadingEngine).findPlug("partition");
                    MPlug setsPlug      = MayaHelper.FindFirstNotConnectedElement(renderPartition.findPlug("sets"));
                    modifier.connect(partitionPlug, setsPlug);
                }
                else
                {
                    MGlobal.displayInfo("SKNFile:Load - Couldn't find Render Partition for mesh: " + name + "." + submesh.Name);
                }

                MPlug outColorPlug      = lambertShader.findPlug("outColor");
                MPlug surfaceShaderPlug = new MFnDependencyNode(shadingEngine).findPlug("surfaceShader");
                modifier.connect(outColorPlug, surfaceShaderPlug);

                MPlug messagePlug      = new MFnDependencyNode(shadingEngine).findPlug("message");
                MPlug shadingGroupPlug = new MFnDependencyNode(materialInfo).findPlug("shadingGroup");
                modifier.connect(messagePlug, shadingGroupPlug);

                modifier.doIt();

                MFnSingleIndexedComponent component = new MFnSingleIndexedComponent();
                MObject   faceComponent             = component.create(MFn.Type.kMeshPolygonComponent);
                MIntArray groupPolygonIndices       = new MIntArray();
                uint      endIndex = (submesh.StartIndex + submesh.IndexCount) / 3;
                for (uint j = submesh.StartIndex / 3; j < endIndex; j++)
                {
                    groupPolygonIndices.append((int)j);
                }
                component.addElements(groupPolygonIndices);

                set.setObject(shadingEngine);
                set.addMember(meshDagPath, faceComponent);
            }

            if (skl == null)
            {
                mesh.updateSurface();
            }
            else
            {
                MFnSkinCluster skinCluster             = new MFnSkinCluster();
                MSelectionList jointPathsSelectionList = new MSelectionList();

                jointPathsSelectionList.add(meshDagPath);
                for (int i = 0; i < skl.Influences.Count; i++)
                {
                    short    jointIndex = skl.Influences[i];
                    SKLJoint joint      = skl.Joints[jointIndex];
                    jointPathsSelectionList.add(skl.JointDagPaths[jointIndex]);

                    MGlobal.displayInfo(string.Format("SKNFile:Load:Bind - Added joint [{0}] {1} to binding selection", joint.ID, joint.Name));
                }

                MGlobal.selectCommand(jointPathsSelectionList);
                MGlobal.executeCommand("skinCluster -mi 4 -tsb -n skinCluster_" + name);

                MPlug      inMeshPlug        = mesh.findPlug("inMesh");
                MPlugArray inMeshConnections = new MPlugArray();
                inMeshPlug.connectedTo(inMeshConnections, true, false);

                if (inMeshConnections.length == 0)
                {
                    MGlobal.displayError("SKNFile:Load:Bind - Failed to find the created Skin Cluster");
                    throw new Exception("SKNFile:Load:Bind - Failed to find the created Skin Cluster");
                }

                MPlug         outputGeometryPlug = inMeshConnections[0];
                MDagPathArray influencesDagPaths = new MDagPathArray();

                skinCluster.setObject(outputGeometryPlug.node);
                skinCluster.influenceObjects(influencesDagPaths);

                MIntArray influenceIndices = new MIntArray((uint)skl.Influences.Count);
                for (int i = 0; i < skl.Influences.Count; i++)
                {
                    MDagPath influencePath = skl.JointDagPaths[skl.Influences[i]];

                    for (int j = 0; j < skl.Influences.Count; j++)
                    {
                        if (influencesDagPaths[j].partialPathName == influencePath.partialPathName)
                        {
                            influenceIndices[i] = j;
                            MGlobal.displayInfo("SKNReader:Load:Bind - Added Influence Joint: " + i + " -> " + j);
                            break;
                        }
                    }
                }

                MFnSingleIndexedComponent singleIndexedComponent = new MFnSingleIndexedComponent();
                MObject   vertexComponent    = singleIndexedComponent.create(MFn.Type.kMeshVertComponent);
                MIntArray groupVertexIndices = new MIntArray((uint)this.Vertices.Count);

                for (int i = 0; i < this.Vertices.Count; i++)
                {
                    groupVertexIndices[i] = i;
                }
                singleIndexedComponent.addElements(groupVertexIndices);

                MGlobal.executeCommand(string.Format("setAttr {0}.normalizeWeights 0", skinCluster.name));

                MDoubleArray weights = new MDoubleArray((uint)(this.Vertices.Count * skl.Influences.Count));
                for (int i = 0; i < this.Vertices.Count; i++)
                {
                    SKNVertex vertex = this.Vertices[i];

                    for (int j = 0; j < 4; j++)
                    {
                        double weight    = vertex.Weights[j];
                        int    influence = vertex.BoneIndices[j];

                        if (weight != 0)
                        {
                            weights[(i * skl.Influences.Count) + influence] = weight;
                        }
                    }
                }

                skinCluster.setWeights(meshDagPath, vertexComponent, influenceIndices, weights, false);
                MGlobal.executeCommand(string.Format("setAttr {0}.normalizeWeights 1", skinCluster.name));
                MGlobal.executeCommand(string.Format("skinPercent -normalize true {0} {1}", skinCluster.name, mesh.name));
                mesh.updateSurface();
            }
        }
Beispiel #26
0
        internal static void decomposeMayaCurve(MDagPath dagnode, MSpace.Space space,
                                                out Point3DCollection controlVertices, out List <double> weights, out List <double> knots, out int degree,
                                                out bool closed, out bool rational)
        {
            var nc     = new MFnNurbsCurve(dagnode);
            var cvct   = nc.numSpans;
            var p_aCVs = new MPointArray();

            degree   = nc.degree;
            closed   = nc.form == MFnNurbsCurve.Form.kPeriodic ? true : false;
            rational = true;
            nc.getCVs(p_aCVs, space);


            controlVertices = new Point3DCollection();
            weights         = new List <double>();
            if (MGlobal.isYAxisUp)
            {
                if (closed)
                {
                    for (var i = 0; i < cvct; i++)
                    {
                        controlVertices.Add(new Point3D(p_aCVs[i].x, p_aCVs[i].y, p_aCVs[i].z));
                        weights.Add(1.0);
                    }
                }
                else
                {
                    foreach (var p in p_aCVs)
                    {
                        controlVertices.Add(new Point3D(p.x, p.y, p.z));
                        weights.Add(1.0);
                    }
                }
            }
            else
            {
                if (closed)
                {
                    for (var i = 0; i < cvct; i++)
                    {
                        controlVertices.Add(new Point3D(p_aCVs[i].x, -p_aCVs[i].z, p_aCVs[i].y));
                        weights.Add(1.0);
                    }
                }
                else
                {
                    foreach (var p in p_aCVs)
                    {
                        controlVertices.Add(new Point3D(p.x, -p.z, p.y));
                        weights.Add(1.0);
                    }
                }
            }

            double min = 0, max = 0;

            nc.getKnotDomain(ref min, ref max);
            var d_aKnots = new MDoubleArray();

            nc.getKnots(d_aKnots);

            knots = new List <double>();
            knots.Add(min);
            knots.AddRange(d_aKnots);
            knots.Add(max);

            nc.Dispose();
            d_aKnots.Dispose();
        }
        public static List <Surface> meshToNurbs(MFnMesh mayaMesh)
        {
            MFnSubd subDmesh = new MFnSubd();

            subDmesh.isIntermediateObject = true;
            MPointArray mayaVerts = new MPointArray();

            mayaMesh.getPoints(mayaVerts, MSpace.Space.kWorld);

            MIntArray polyVertct = new MIntArray();


            MIntArray ids    = new MIntArray();
            MIntArray idList = new MIntArray();

            for (int i = 0; i < mayaMesh.numPolygons; i++)
            {
                mayaMesh.getPolygonVertices(i, ids);
                foreach (var id in ids)
                {
                    idList.Add(id);
                }
                polyVertct.Add(ids.Count);
            }
            subDmesh.createBaseMesh(false, mayaMesh.numVertices, mayaMesh.numPolygons, mayaVerts, polyVertct, idList);

            try
            {
                MUintArray   creaseEdgId   = new MUintArray();
                MDoubleArray creaseEdgeVal = new MDoubleArray();
                mayaMesh.getCreaseEdges(creaseEdgId, creaseEdgeVal);

                foreach (var edgId in creaseEdgId)
                {
                    subDmesh.edgeSetCrease(edgId, true);
                }
            }
            catch {}

            try
            {
                MUintArray   creaseVertId  = new MUintArray();
                MDoubleArray creaseVertVal = new MDoubleArray();
                mayaMesh.getCreaseVertices(creaseVertId, creaseVertVal);

                foreach (var vertId in creaseVertId)
                {
                    subDmesh.vertexSetCrease(vertId, true);
                }
            }
            catch { }


            subDmesh.updateAllEditsAndCreases();

            MObjectArray nurbsSurfs = new MObjectArray();

            subDmesh.convertToNurbs(nurbsSurfs);

            List <MFnNurbsSurface> mfnSurfaceList = new List <MFnNurbsSurface>(nurbsSurfs.Count);

            foreach (var surf in nurbsSurfs)
            {
                mfnSurfaceList.Add(new MFnNurbsSurface(surf));
            }

            List <Surface> dynSurfaceList = new List <Surface>(mfnSurfaceList.Count);

            foreach (var mfnNS in mfnSurfaceList)
            {
                dynSurfaceList.Add(DMSurface.mNurbsSurfaceToDynamoSurface(mfnNS, MSpace.Space.kObject));
            }

            MGlobal.deleteNode(subDmesh.model);
            return(dynSurfaceList);
        }
        public override void writeDoubleArray(MDoubleArray array)
        {
            if (myCurrentChanelNode != null)
            {
                uint size = array.length;
                XmlNode sizeNode = myXmlDoc.CreateElement(sizeTag);
                sizeNode.InnerText = Convert.ToString(size);
                myCurrentChanelNode.AppendChild(sizeNode);

                XmlNode arrayNode = myXmlDoc.CreateElement(doubleArrayTag);
                myCurrentChanelNode.AppendChild(arrayNode);

                for (int i = 0; i < size; i++)
                {
                    string value = array[i].ToString();
                    XmlNode valueNode = myXmlDoc.CreateElement("value");
                    arrayNode.AppendChild(valueNode);
                }
            }

            return;
        }
Beispiel #29
0
		private unsafe void apply(
		MDataBlock block,
		uint receptorSize,
		MDoubleArray magnitudeArray,
		MDoubleArray magnitudeOwnerArray,
		MVectorArray directionArray,
		MVectorArray directionOwnerArray,
		MVectorArray outputForce
		)
		//
		//      Compute output force for each particle.  If there exists the 
		//      corresponding per particle attribute, use the data passed from
		//      particle shape (stored in magnitudeArray and directionArray).  
		//      Otherwise, use the attribute value from the field.
		//
		{
			// get the default values
			MVector defaultDir = direction(block);
			double defaultMag = magnitude(block);
			uint magArraySize = magnitudeArray.length;
			uint dirArraySize = directionArray.length;
			uint magOwnerArraySize = magnitudeOwnerArray.length;
			uint dirOwnerArraySize = directionOwnerArray.length;
			uint numOfOwner = magOwnerArraySize;
			if (dirOwnerArraySize > numOfOwner)
				numOfOwner = dirOwnerArraySize;

			double m_magnitude = defaultMag;
			MVector m_direction = defaultDir;

			for (int ptIndex = 0; ptIndex < receptorSize; ptIndex++)
			{
				if (receptorSize == magArraySize)
					m_magnitude = magnitudeArray[ptIndex];
				if (receptorSize == dirArraySize)
					m_direction = directionArray[ptIndex];
				if (numOfOwner > 0)
				{
					for (int nthOwner = 0; nthOwner < numOfOwner; nthOwner++)
					{
						if (magOwnerArraySize == numOfOwner)
							m_magnitude = magnitudeOwnerArray[nthOwner];
						if (dirOwnerArraySize == numOfOwner)
							m_direction = directionOwnerArray[nthOwner];
						outputForce.append(m_direction * m_magnitude);
					}
				}
				else
				{
					outputForce.append(m_direction * m_magnitude);
				}
			}
		}
Beispiel #30
0
        private List <BabylonAnimation> GetAnimationsFrameByFrame(MFnTransform mFnTransform)
        {
            int start = Loader.GetMinTime();
            int end   = Loader.GetMaxTime();

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

            string[] babylonAnimationProperties = new string[] { "scaling", "rotationQuaternion", "position", "visibility" };


            Dictionary <string, List <BabylonAnimationKey> > keysPerProperty = new Dictionary <string, List <BabylonAnimationKey> >();

            keysPerProperty.Add("scaling", new List <BabylonAnimationKey>());
            keysPerProperty.Add("rotationQuaternion", new List <BabylonAnimationKey>());
            keysPerProperty.Add("position", new List <BabylonAnimationKey>());
            keysPerProperty.Add("visibility", new List <BabylonAnimationKey>());

            // get keys
            for (int currentFrame = start; currentFrame <= end; currentFrame++)
            {
                // get transformation matrix at this frame
                MDoubleArray mDoubleMatrix = new MDoubleArray();
                MGlobal.executeCommand($"getAttr -t {currentFrame} {mFnTransform.fullPathName}.matrix", mDoubleMatrix);
                mDoubleMatrix.get(out float[] localMatrix);
                MMatrix matrix = new MMatrix(localMatrix);
                var     transformationMatrix = new MTransformationMatrix(matrix);

                // Retreive TRS vectors from matrix
                var position           = transformationMatrix.getTranslation();
                var rotationQuaternion = transformationMatrix.getRotationQuaternion();
                var scaling            = transformationMatrix.getScale();

                // Switch coordinate system at object level
                position[2]           *= -1;
                rotationQuaternion[0] *= -1;
                rotationQuaternion[1] *= -1;

                // create animation key for each property
                for (int indexAnimation = 0; indexAnimation < babylonAnimationProperties.Length; indexAnimation++)
                {
                    string babylonAnimationProperty = babylonAnimationProperties[indexAnimation];

                    BabylonAnimationKey key = new BabylonAnimationKey();
                    key.frame = currentFrame;
                    switch (indexAnimation)
                    {
                    case 0:     // scaling
                        key.values = scaling.ToArray();
                        break;

                    case 1:     // rotationQuaternion
                        key.values = rotationQuaternion.ToArray();
                        break;

                    case 2:     // position
                        key.values = position.ToArray();
                        break;

                    case 3:     // visibility
                        key.values = new float[] { Loader.GetVisibility(mFnTransform.fullPathName, currentFrame) };
                        break;
                    }

                    keysPerProperty[babylonAnimationProperty].Add(key);
                }
            }

            // create animation for each property
            for (int indexAnimation = 0; indexAnimation < babylonAnimationProperties.Length; indexAnimation++)
            {
                string babylonAnimationProperty = babylonAnimationProperties[indexAnimation];

                List <BabylonAnimationKey> keys = keysPerProperty[babylonAnimationProperty];

                var keysFull = new List <BabylonAnimationKey>(keys);

                // Optimization
                OptimizeAnimations(keys, true);

                // Ensure animation has at least 2 frames
                if (IsAnimationKeysRelevant(keys))
                {
                    int dataType = 0;                               // "scaling", "rotationQuaternion", "position", "visibility"
                    if (indexAnimation == 0 || indexAnimation == 2) // scaling and position
                    {
                        dataType = (int)BabylonAnimation.DataType.Vector3;
                    }
                    else if (indexAnimation == 1)    // rotationQuaternion
                    {
                        dataType = (int)BabylonAnimation.DataType.Quaternion;
                    }
                    else   // visibility
                    {
                        dataType = (int)BabylonAnimation.DataType.Float;
                    }
                    // Create BabylonAnimation
                    animations.Add(new BabylonAnimation()
                    {
                        dataType       = dataType,
                        name           = babylonAnimationProperty + " animation",
                        framePerSecond = Loader.GetFPS(),
                        loopBehavior   = (int)BabylonAnimation.LoopBehavior.Cycle,
                        property       = babylonAnimationProperty,
                        keys           = keys.ToArray(),
                        keysFull       = keysFull
                    });
                }
            }
            return(animations);
        }
Beispiel #31
0
		private void doSimpleSolver()
		//
		// Solve single joint in the x-y plane
		//
		// - first it calculates the angle between the handle and the end-effector.
		// - then it determines which way to rotate the joint.
		//
		{
			// Get the handle and create a function set for it
			//
			MIkHandleGroup handle_group = handleGroup;
			if (null == handle_group) {
				throw new System.InvalidOperationException("invalid handle group.");
			}

			MObject handle = handle_group.handle( 0 );
			MDagPath handlePath = MDagPath.getAPathTo( handle );
			MFnIkHandle fnHandle = new MFnIkHandle( handlePath );

			// Get the position of the end_effector
			//
			MDagPath end_effector = new MDagPath();
			fnHandle.getEffector(end_effector);
			MFnTransform tran = new MFnTransform( end_effector );
			MPoint effector_position = tran.rotatePivot( MSpace.Space.kWorld );

			// Get the position of the handle
			//
			MPoint handle_position = fnHandle.rotatePivot( MSpace.Space.kWorld );

			// Get the start joint position
			//
			MDagPath start_joint = new MDagPath();
			fnHandle.getStartJoint( start_joint );
			MFnTransform start_transform = new MFnTransform( start_joint );
			MPoint start_position = start_transform.rotatePivot( MSpace.Space.kWorld );

			// Calculate the rotation angle
			//
			MVector v1 = start_position.minus( effector_position );
			MVector v2 = start_position.minus( handle_position );
			double angle = v1.angle( v2 );

			// -------- Figure out which way to rotate --------
			//
			//  define two vectors U and V as follows
			//  U   =   EndEffector(E) - StartJoint(S)
			//  N   =   Normal to U passing through EndEffector
			//
			//  Clip handle_position to half-plane U to determine the region it
			//  lies in. Use the region to determine  the rotation direction.
			//
			//             U
			//             ^              Region      Rotation
			//             |  B           
			//            (E)---N            A          C-C-W
			//         A   |                 B           C-W
			//             |  B
			//             |
			//            (S)
			//
			double rot = 0.0;	// Rotation about Z-axis

			// U and N define a half-plane to clip the handle against
			//
			MVector U = effector_position.minus( start_position );
			U.normalize();

			// Get a normal to U
			//
			MVector zAxis = new MVector( 0.0, 0.0, 1.0 );
			MVector N = U.crossProduct( zAxis );	// Cross product
			N.normalize();

			// P is the handle position vector
			//
			MVector P = handle_position.minus( effector_position );

			// Determine the rotation direction
			//
			double PdotN = P[0]*N[0] + P[1]*N[1];
			if ( PdotN < 0 ) {
				// counter-clockwise
				rot = angle;
			} else {
				// clockwise
				rot = -1.0 * angle;
			}

			// get and set the Joint Angles 
			//
			MDoubleArray jointAngles = new MDoubleArray();
			getJointAngles( jointAngles );
			jointAngles.set( jointAngles[0] + rot, 0 );
			setJointAngles( jointAngles );
		}
Beispiel #32
0
        //
        //      Compute output force for each particle.  If there exists the
        //      corresponding per particle attribute, use the data passed from
        //      particle shape (stored in magnitudeArray and directionArray).
        //      Otherwise, use the attribute value from the field.
        //
        private unsafe void apply(
            MDataBlock block,
            uint receptorSize,
            MDoubleArray magnitudeArray,
            MDoubleArray magnitudeOwnerArray,
            MVectorArray directionArray,
            MVectorArray directionOwnerArray,
            MVectorArray outputForce
            )
        {
            // get the default values
            MVector defaultDir = direction(block);
            double defaultMag = magnitude(block);
            uint magArraySize = magnitudeArray.length;
            uint dirArraySize = directionArray.length;
            uint magOwnerArraySize = magnitudeOwnerArray.length;
            uint dirOwnerArraySize = directionOwnerArray.length;
            uint numOfOwner = magOwnerArraySize;
            if (dirOwnerArraySize > numOfOwner)
                numOfOwner = dirOwnerArraySize;

            double m_magnitude = defaultMag;
            MVector m_direction = defaultDir;

            for (int ptIndex = 0; ptIndex < receptorSize; ptIndex++)
            {
                if (receptorSize == magArraySize)
                    m_magnitude = magnitudeArray[ptIndex];
                if (receptorSize == dirArraySize)
                    m_direction = directionArray[ptIndex];
                if (numOfOwner > 0)
                {
                    for (int nthOwner = 0; nthOwner < numOfOwner; nthOwner++)
                    {
                        if (magOwnerArraySize == numOfOwner)
                            m_magnitude = magnitudeOwnerArray[nthOwner];
                        if (dirOwnerArraySize == numOfOwner)
                            m_direction = directionOwnerArray[nthOwner];
                        outputForce.append(m_direction * m_magnitude);
                    }
                }
                else
                {
                    outputForce.append(m_direction * m_magnitude);
                }
            }
        }
Beispiel #33
0
        /// <summary>
        /// Get TRS and visiblity animations of the transform
        /// </summary>
        /// <param name="transform">Transform above mesh/camera/light</param>
        /// <returns></returns>
        private List <BabylonAnimation> GetAnimation(MFnTransform transform)
        {
            // Animations
            MPlugArray   connections  = new MPlugArray();
            MStringArray animCurvList = new MStringArray();
            MIntArray    keysTime     = new MIntArray();
            MDoubleArray keysValue    = new MDoubleArray();

            MFloatArray translateValues  = new MFloatArray();
            MFloatArray rotateValues     = new MFloatArray();
            MFloatArray scaleValues      = new MFloatArray();
            MFloatArray visibilityValues = new MFloatArray();
            MFloatArray keyTimes         = new MFloatArray();

            List <BabylonAnimationKey> keys             = new List <BabylonAnimationKey>();
            List <BabylonAnimation>    animationsObject = new List <BabylonAnimation>();

            //Get the animCurve
            MGlobal.executeCommand("listConnections -type \"animCurve\" " + transform.fullPathName + ";", animCurvList);

            List <AnimCurvData> animCurvesData = new List <AnimCurvData>();

            foreach (String animCurv in animCurvList)
            {
                AnimCurvData animCurvData = new AnimCurvData();
                animCurvesData.Add(animCurvData);

                animCurvData.animCurv = animCurv;

                //Get the key time for each curves
                MGlobal.executeCommand("keyframe -q " + animCurv + ";", keysTime);

                //Get the value for each curves
                MGlobal.executeCommand("keyframe - q -vc -absolute " + animCurv + ";", keysValue);

                if (animCurv.EndsWith("translateZ") || animCurv.EndsWith("rotateX") || animCurv.EndsWith("rotateY"))
                {
                    for (int index = 0; index < keysTime.Count; index++)
                    {
                        // Switch coordinate system at object level
                        animCurvData.valuePerFrame.Add(keysTime[index], (float)keysValue[index] * -1.0f);
                    }
                }
                else
                {
                    for (int index = 0; index < keysTime.Count; index++)
                    {
                        animCurvData.valuePerFrame.Add(keysTime[index], (float)keysValue[index]);
                    }
                }
            }

            string[] mayaAnimationProperties    = new string[] { "translate", "rotate", "scale" };
            string[] babylonAnimationProperties = new string[] { "position", "rotationQuaternion", "scaling" };
            string[] axis = new string[] { "X", "Y", "Z" };

            // Init TRS default values
            Dictionary <string, float> defaultValues = new Dictionary <string, float>();

            float[] position           = null;
            float[] rotationQuaternion = null;
            float[] rotation           = null;
            float[] scaling            = null;
            GetTransform(transform, ref position, ref rotationQuaternion, ref rotation, ref scaling); // coordinate system already switched
            defaultValues.Add("translateX", position[0]);
            defaultValues.Add("translateY", position[1]);
            defaultValues.Add("translateZ", position[2]);
            defaultValues.Add("rotateX", rotation[0]);
            defaultValues.Add("rotateY", rotation[1]);
            defaultValues.Add("rotateZ", rotation[2]);
            defaultValues.Add("scaleX", scaling[0]);
            defaultValues.Add("scaleY", scaling[1]);
            defaultValues.Add("scaleZ", scaling[2]);

            for (int indexAnimationProperty = 0; indexAnimationProperty < mayaAnimationProperties.Length; indexAnimationProperty++)
            {
                string mayaAnimationProperty = mayaAnimationProperties[indexAnimationProperty];

                // Retreive animation curves data for current animation property
                // Ex: all "translate" data are "translateX", "translateY", "translateZ"
                List <AnimCurvData> animDataProperty = animCurvesData.Where(data => data.animCurv.Contains(mayaAnimationProperty)).ToList();

                if (animDataProperty.Count == 0)
                {
                    // Property is not animated
                    continue;
                }

                // Get all frames for this property
                List <int> framesProperty = new List <int>();
                foreach (var animData in animDataProperty)
                {
                    framesProperty.AddRange(animData.valuePerFrame.Keys);
                }
                framesProperty = framesProperty.Distinct().ToList();
                framesProperty.Sort();

                // Get default values for this property
                BabylonAnimationKey lastBabylonAnimationKey = new BabylonAnimationKey();
                lastBabylonAnimationKey.frame  = 0;
                lastBabylonAnimationKey.values = new float[] { defaultValues[mayaAnimationProperty + "X"], defaultValues[mayaAnimationProperty + "Y"], defaultValues[mayaAnimationProperty + "Z"] };

                // Compute all values for this property
                List <BabylonAnimationKey> babylonAnimationKeys = new List <BabylonAnimationKey>();
                foreach (var frameProperty in framesProperty)
                {
                    BabylonAnimationKey babylonAnimationKey = new BabylonAnimationKey();
                    babylonAnimationKeys.Add(babylonAnimationKey);

                    // Frame
                    babylonAnimationKey.frame = frameProperty;

                    // Values
                    float[] valuesProperty = new float[3];
                    for (int indexAxis = 0; indexAxis < axis.Length; indexAxis++)
                    {
                        AnimCurvData animCurvDataAxis = animDataProperty.Find(data => data.animCurv.EndsWith(axis[indexAxis]));

                        float value;
                        if (animCurvDataAxis != null && animCurvDataAxis.valuePerFrame.ContainsKey(frameProperty))
                        {
                            value = animCurvDataAxis.valuePerFrame[frameProperty];
                        }
                        else
                        {
                            value = lastBabylonAnimationKey.values[indexAxis];
                        }
                        valuesProperty[indexAxis] = value;
                    }
                    babylonAnimationKey.values = valuesProperty.ToArray();

                    // Update last known values
                    lastBabylonAnimationKey = babylonAnimationKey;
                }

                // Convert euler to quaternion angles
                if (indexAnimationProperty == 1) // Rotation
                {
                    foreach (var babylonAnimationKey in babylonAnimationKeys)
                    {
                        BabylonVector3    eulerAngles      = BabylonVector3.FromArray(babylonAnimationKey.values);
                        BabylonQuaternion quaternionAngles = eulerAngles.toQuaternion();
                        babylonAnimationKey.values = quaternionAngles.ToArray();
                    }
                }

                var keysFull = new List <BabylonAnimationKey>(babylonAnimationKeys);

                // Optimization
                OptimizeAnimations(babylonAnimationKeys, true);

                // Ensure animation has at least 2 frames
                if (IsAnimationKeysRelevant(keys))
                {
                    // Create BabylonAnimation
                    string babylonAnimationProperty = babylonAnimationProperties[indexAnimationProperty];
                    animationsObject.Add(new BabylonAnimation()
                    {
                        dataType       = indexAnimationProperty == 1 ? (int)BabylonAnimation.DataType.Quaternion : (int)BabylonAnimation.DataType.Vector3,
                        name           = babylonAnimationProperty + " animation",
                        framePerSecond = 30,
                        loopBehavior   = (int)BabylonAnimation.LoopBehavior.Cycle,
                        property       = babylonAnimationProperty,
                        keys           = babylonAnimationKeys.ToArray(),
                        keysFull       = keysFull
                    });
                }
            }

            return(animationsObject);
        }
Beispiel #34
0
		public override bool compute(MPlug plug, MDataBlock dataBlock)
		//
		//	Descriptions:
		//		compute output force.
		//
		{
			if (plug.notEqual(mOutputForce))
                return false;

			// get the logical index of the element this plug refers to.
			//
			uint multiIndex = plug.logicalIndex;

			// Get input data handle, use outputArrayValue since we do not
			// want to evaluate both inputs, only the one related to the
			// requested multiIndex. Evaluating both inputs at once would cause
			// a dependency graph loop.

			MArrayDataHandle hInputArray = dataBlock.outputArrayValue(mInputData);
			hInputArray.jumpToElement(multiIndex);

			// get children of aInputData.

			MDataHandle hCompond = hInputArray.inputValue();

			MDataHandle hPosition = hCompond.child(mInputPositions);
			MObject dPosition = hPosition.data();
			MFnVectorArrayData fnPosition = new MFnVectorArrayData(dPosition);
			MVectorArray points = fnPosition.array();

			// The attribute mInputPPData contains the attribute in an array form 
			// prepared by the particleShape if the particleShape has per particle 
			// attribute fieldName_attrName.  
			//
			// Suppose a field with the name dynExprField1 is connecting to 
			// particleShape1, and the particleShape1 has per particle float attribute
			// dynExprField1_magnitude and vector attribute dynExprField1_direction,
			// then hInputPPArray will contains a MdoubleArray with the corresponding
			// name "magnitude" and a MvectorArray with the name "direction".  This 
			// is a mechanism to allow the field attributes being driven by dynamic 
			// expression.
			MArrayDataHandle mhInputPPData = dataBlock.inputArrayValue(mInputPPData);
			mhInputPPData.jumpToElement(multiIndex);
			
			MDataHandle hInputPPData = mhInputPPData.inputValue();
			MObject dInputPPData = hInputPPData.data();
			MFnArrayAttrsData inputPPArray = new MFnArrayAttrsData(dInputPPData);

			MDataHandle hOwnerPPData = dataBlock.inputValue(mOwnerPPData);
			MObject dOwnerPPData = hOwnerPPData.data();
			MFnArrayAttrsData ownerPPArray = new MFnArrayAttrsData(dOwnerPPData);

			string magString = "magnitude";
			MFnArrayAttrsData.Type doubleType = MFnArrayAttrsData.Type.kDoubleArray;

			bool arrayExist;
			MDoubleArray magnitudeArray;
			arrayExist = inputPPArray.checkArrayExist(magString, out doubleType);
            if (arrayExist)
            {
                magnitudeArray = inputPPArray.getDoubleData(magString);
            }
            else
            {
                magnitudeArray = new MDoubleArray();
            }
		   
			MDoubleArray magnitudeOwnerArray;
			arrayExist = ownerPPArray.checkArrayExist(magString, out doubleType);
			if (arrayExist)
			{
				magnitudeOwnerArray = ownerPPArray.getDoubleData(magString);
            }
            else
            {
                magnitudeOwnerArray = new MDoubleArray();
            }

			string dirString = "direction";
			MFnArrayAttrsData.Type vectorType = MFnArrayAttrsData.Type.kVectorArray;
			MVectorArray directionArray;
			arrayExist = inputPPArray.checkArrayExist(dirString, out vectorType);
            if (arrayExist)
            {
                directionArray = inputPPArray.getVectorData(dirString);
            }
            else
            {
                directionArray = new MVectorArray();
            }
		 
			MVectorArray directionOwnerArray;
			arrayExist = ownerPPArray.checkArrayExist(dirString, out vectorType);
            if (arrayExist)
            {
                directionOwnerArray = ownerPPArray.getVectorData(dirString);
            }
            else
            {
                directionOwnerArray = new MVectorArray();
            }

			// Compute the output force.
			//
			MVectorArray forceArray = new MVectorArray();

			apply(dataBlock, points.length, magnitudeArray, magnitudeOwnerArray,
				   directionArray, directionOwnerArray, forceArray);

			// get output data handle
			//
			MArrayDataHandle hOutArray = dataBlock.outputArrayValue(mOutputForce);
			MArrayDataBuilder bOutArray = hOutArray.builder();

			// get output force array from block.
			//
			MDataHandle hOut = bOutArray.addElement(multiIndex);
			MFnVectorArrayData fnOutputForce = new MFnVectorArrayData();
			MObject dOutputForce = fnOutputForce.create(forceArray);

			// update data block with new output force data.
			//
			hOut.set(dOutputForce);
			dataBlock.setClean(plug);

			return true;
		}
Beispiel #35
0
        private Dictionary <string, object> _ExportCustomUserAttributes(BaseObject baseObject)
        {
            var objectName = "";

            if (baseObject.mFnTransform != null)
            {
                objectName = baseObject.mFnTransform.name;
            }
            else if (baseObject.babylonMaterial != null)
            {
                objectName = baseObject.babylonMaterial.name;
            }

            MStringArray customAttributeNamesMStringArray = new MStringArray();
            Dictionary <string, object> customsAttributes = new Dictionary <string, object>();

            MGlobal.executeCommand($"listAttr -ud {objectName}", customAttributeNamesMStringArray);

            var customAttributeNames = customAttributeNamesMStringArray.Where((attributeName) => { return(!_DisallowedCustomAttributeNames.Contains(attributeName)); });

            foreach (string name in customAttributeNames)
            {
                MStringArray type = new MStringArray();

                MGlobal.executeCommand($"getAttr -type {objectName}.{name}", type);

                switch (type[0])
                {
                case "double":
                    double floatValue = 0;
                    MGlobal.executeCommand($"getAttr {objectName}.{name}", out floatValue);
                    customsAttributes.Add(name, floatValue);
                    break;

                case "bool":
                    int boolBinValue = 0;
                    MGlobal.executeCommand($"getAttr {objectName}.{name}", out boolBinValue);
                    customsAttributes.Add(name, boolBinValue);
                    break;

                case "long":
                    int intValue = 0;
                    MGlobal.executeCommand($"getAttr {objectName}.{name}", out intValue);
                    customsAttributes.Add(name, intValue);
                    break;

                case "string":
                    string stringValue = "";
                    MGlobal.executeCommand($"getAttr {objectName}.{name}", out stringValue);
                    customsAttributes.Add(name, stringValue);
                    break;

                case "enum":
                    int enumValue = 0;
                    MGlobal.executeCommand($"getAttr {objectName}.{name}", out enumValue);
                    customsAttributes.Add(name, enumValue);
                    break;

                case "double3":
                    MDoubleArray vectorValue = new MDoubleArray();
                    MGlobal.executeCommand($"getAttr {objectName}.{name}", vectorValue);
                    customsAttributes.Add(name, vectorValue);
                    break;

                default:
                    MCommandResult attrValue = new MCommandResult();
                    MGlobal.executeCommand($"getAttr {objectName}.{name}", attrValue);
                    customsAttributes.Add(name, attrValue);
                    break;
                }
            }

            foreach (string name in customAttributeNames)
            {
                if (customsAttributes.ContainsKey(name + "X") && customsAttributes.ContainsKey(name + "Y") && customsAttributes.ContainsKey(name + "Z"))
                {
                    customsAttributes.Remove(name + "X");
                    customsAttributes.Remove(name + "Y");
                    customsAttributes.Remove(name + "Z");
                }
            }

            return(customsAttributes);
        }
        public override void doIt(MArgList args)
        {
            // parse args to get the file name from the command-line
            //
            parseArgs(args);
            uint count = 0;

            // Iterate through graph and search for skinCluster nodes
            //
            MItDependencyNodes iter = new MItDependencyNodes( MFn.Type.kInvalid);
            for ( ; !iter.isDone; iter.next() )
            {
                MObject obj = iter.item;
                if (obj.apiType == MFn.Type.kSkinClusterFilter)
                {
                    count++;

                    // For each skinCluster node, get the list of influence objects
                    //
                    MFnSkinCluster skinCluster = new MFnSkinCluster(obj);
                    MDagPathArray infs = new MDagPathArray();
                    uint nInfs;
                    try
                    {
                        nInfs = skinCluster.influenceObjects(infs);
                    }
                    catch (Exception)
                    {
                        MGlobal.displayInfo("Error getting influence objects.");
                        continue;
                    }
                    if (0 == nInfs)
                    {
                        MGlobal.displayInfo("Error: No influence objects found.");
                        continue;
                    }

                    // loop through the geometries affected by this cluster
                    //
                    uint nGeoms = skinCluster.numOutputConnections;
                    for (uint ii = 0; ii < nGeoms; ++ii)
                    {
                        uint index;
                        try
                        {
                            index = skinCluster.indexForOutputConnection(ii);
                        }
                        catch (Exception)
                        {
                            MGlobal.displayInfo("Error getting geometry index.");
                            continue;
                        }

                        // get the dag path of the ii'th geometry
                        //
                        MDagPath skinPath = new MDagPath();
                        try{
                        skinCluster.getPathAtIndex(index,skinPath);
                        }
                        catch (Exception)
                        {
                            MGlobal.displayInfo("Error getting geometry path.");
                            continue;
                        }

                        // iterate through the components of this geometry
                        //
                        MItGeometry gIter = new MItGeometry(skinPath);

                        // print out the path name of the skin, vertexCount & influenceCount
                        //
                        UnicodeEncoding uniEncoding = new UnicodeEncoding();
                        string res = String.Format("{0} {1} {2}\n",skinPath.partialPathName,gIter.count,nInfs);
                        file.Write(uniEncoding.GetBytes(res),0,uniEncoding.GetByteCount(res));

                        // print out the influence objects
                        //
                        for (int kk = 0; kk < nInfs; ++kk)
                        {
                            res = String.Format("{0} ", infs[kk].partialPathName);
                            file.Write(uniEncoding.GetBytes(res),0,uniEncoding.GetByteCount(res));
                        }
                        res = "\n";
                        file.Write(uniEncoding.GetBytes(res), 0, uniEncoding.GetByteCount(res));

                        for ( /* nothing */ ; !gIter.isDone; gIter.next() ) {
                            MObject comp;
                            try
                            {
                                comp = gIter.component;
                            }
                            catch (Exception)
                            {
                                MGlobal.displayInfo("Error getting geometry path.");
                                continue;
                            }

                            // Get the weights for this vertex (one per influence object)
                            //
                            MDoubleArray wts = new MDoubleArray();
                            uint infCount = 0;
                            try
                            {
                                skinCluster.getWeights(skinPath, comp, wts, ref infCount);
                            }
                            catch (Exception)
                            {
                                displayError("Error getting weights.");
                                continue;
                            }
                            if (0 == infCount)
                            {
                                displayError("Error: 0 influence objects.");
                            }

                            // Output the weight data for this vertex
                            //
                            res = String.Format("{0} ",gIter.index);
                            file.Write(uniEncoding.GetBytes(res), 0, uniEncoding.GetByteCount(res));
                            for (int jj = 0; jj < infCount ; ++jj )
                            {
                                res = String.Format("{0} ", wts[jj]);
                                file.Write(uniEncoding.GetBytes(res), 0, uniEncoding.GetByteCount(res));
                            }
                            file.Write(uniEncoding.GetBytes("\n"), 0, uniEncoding.GetByteCount("\n"));
                        }
                    }
                }
            }

            if (0 == count)
            {
                displayError("No skinClusters found in this scene.");
            }
            file.Close();
            return;
        }
Beispiel #37
0
        public static void ToMaya(Curve CurveToSend, string name)
        {
            NurbsCurve ctsAsNurb = null;

            if (CurveToSend is Rectangle)
            {
                Rectangle rec = (Rectangle)CurveToSend;
                ctsAsNurb = NurbsCurve.ByControlPoints(rec.Points, 1, true);
            }
            else if (CurveToSend is Polygon)
            {
                Polygon rec = (Polygon)CurveToSend;
                ctsAsNurb = NurbsCurve.ByControlPoints(rec.Points, 1, true);
            }
            else
            {
                ctsAsNurb = CurveToSend.ToNurbsCurve();
            }

            var ncd = new MFnNurbsCurveData();


            MFnNurbsCurveForm mfnform;

            if (ctsAsNurb.IsClosed)
            {
                mfnform = MFnNurbsCurveForm.kClosed;
            }
            else
            {
                mfnform = MFnNurbsCurveForm.kOpen;
            }

            var mayaCurve = new MFnNurbsCurve();

            var vtxs = new MPointArray();

            var cvs = ctsAsNurb.ControlPoints();
            var yUp = MGlobal.isYAxisUp;

            if (yUp)
            {
                foreach (var cv in cvs)
                {
                    var pt = new MPoint(cv.X, cv.Z, -cv.Y);
                    vtxs.Add(pt);
                    //pt.Dispose();
                }
            }
            else
            {
                foreach (var cv in cvs)
                {
                    var pt = new MPoint(cv.X, cv.Y, cv.Z);
                    vtxs.Add(pt);
                    //pt.Dispose();
                }
            }

            var knots    = ctsAsNurb.Knots();
            var crvKnots = new MDoubleArray(knots);

            crvKnots.RemoveAt(0);
            crvKnots.RemoveAt(crvKnots.Count - 1);

            MDagPath node       = null;
            var      nodeExists = false;

            Task checkNode  = null;
            Task deleteNode = null;

            try
            {
                node       = DMInterop.getDagNode(name);
                nodeExists = true;
            }
            catch (Exception)
            {
                nodeExists = false;
            }

            MObject obj;

            if (nodeExists)
            {
                MDagPath nodeShape = node;
                nodeShape.extendToShape();
                var modifyCrv = new MDGModifier();
                mayaCurve = new MFnNurbsCurve(nodeShape);

                try
                {
                    MFnNurbsCurveData dataCreator  = new MFnNurbsCurveData();
                    MObject           outCurveData = dataCreator.create();
                    var    span   = (vtxs.Count - ctsAsNurb.Degree);
                    string rblCmd = $"rebuildCurve -rt 0 -s {span} -d {ctsAsNurb.Degree} {name}";

                    if (mayaCurve.numCVs != vtxs.Count || mayaCurve.degree != ctsAsNurb.Degree)
                    {
                        MGlobal.executeCommand(rblCmd);
                    }

                    mayaCurve.setCVs(vtxs);
                    mayaCurve.setKnots(crvKnots, 0, crvKnots.length - 1);
                    mayaCurve.updateCurve();
                    modifyCrv.doIt();

                    if (CurveToSend.GetType() == typeof(Circle))
                    {
                        span   = 8;
                        rblCmd = $"rebuildCurve -rt 0 -s {span} {name}";
                        MGlobal.executeCommand(rblCmd);
                    }
                }
                catch (Exception e)
                {
                    MGlobal.displayWarning(e.Message);
                }
            }

            else
            {
                obj = mayaCurve.create(vtxs, crvKnots, (uint)ctsAsNurb.Degree, (MFnNurbsCurve.Form)mfnform,
                                       false, ctsAsNurb.IsRational);
                MFnDependencyNode nodeFn = new MFnDagNode(obj);
                nodeFn.setName(name);
            }
        }
Beispiel #38
0
        public static void ExportXModel(string FilePath, XModelType FileType, bool Siege = false, string Cosmetic = "")
        {
            // Configure scene
            using (var MayaCfg = new MayaSceneConfigure())
            {
                // First, get the current selection
                var ExportObjectList = new MSelectionList();
                MGlobal.getActiveSelectionList(ExportObjectList);

                // If empty, select all joints and meshes
                if (ExportObjectList.length == 0)
                {
                    // Select all joints and meshes
                    MGlobal.executeCommand("string $selected[] = `ls -type joint`; select -r $selected;");
                    MGlobal.executeCommand("string $transforms[] = `ls -tr`;string $polyMeshes[] = `filterExpand -sm 12 $transforms`;select -add $polyMeshes;");

                    // Get it again
                    MGlobal.getActiveSelectionList(ExportObjectList);
                }

                // If still empty, error blank scene
                if (ExportObjectList.length == 0)
                {
                    MGlobal.displayError("[CODTools] The current scene is empty...");
                    return;
                }

                // Progress
                MayaCfg.StartProgress("Exporting XModel...", (int)ExportObjectList.length);

                // Create new model
                var Result = new XModel(System.IO.Path.GetFileNameWithoutExtension(FilePath));
                // Assign siege model flag (Default: false)
                Result.SiegeModel = Siege;

                // Metadata
                var SceneName = string.Empty;
                MGlobal.executeCommand("file -q -sceneName", out SceneName);

                Result.Comments.Add(string.Format("Export filename: '{0}'", FilePath));
                Result.Comments.Add(string.Format("Source filename: '{0}'", SceneName));
                Result.Comments.Add(string.Format("Export time: {0}", DateTime.Now.ToString()));

                // Iterate and add joints
                var ParentStack = new List <string>();
                var UniqueBones = new HashSet <string>();

                foreach (var Joint in ExportObjectList.DependNodes(MFn.Type.kJoint))
                {
                    // Step
                    MayaCfg.StepProgress();

                    // Grab the controller
                    var Path       = GetObjectDagPath(Joint);
                    var Controller = new MFnIkJoint(Path);

                    // Create a new bone
                    var TagName = CleanNodeName(Controller.name);

                    if (UniqueBones.Contains(TagName))
                    {
                        continue;
                    }
                    UniqueBones.Add(TagName);

                    var NewBone = new Bone(TagName);
                    // Add parent
                    ParentStack.Add(GetParentName(Controller));

                    // Fetch the world-space position and rotation
                    var WorldPosition = Controller.getTranslation(MSpace.Space.kWorld);

                    var WorldRotation = new MQuaternion(MQuaternion.identity);
                    Controller.getRotation(WorldRotation, MSpace.Space.kWorld);

                    var WorldScale = new double[3] {
                        1, 1, 1
                    };
                    Controller.getScale(WorldScale);

                    // Create the matrix
                    NewBone.Translation    = WorldPosition * (1 / 2.54);
                    NewBone.Scale          = new MVector(WorldScale[0], WorldScale[1], WorldScale[2]);
                    NewBone.RotationMatrix = WorldRotation.asMatrix;

                    // Add it
                    Result.Bones.Add(NewBone);
                }
                // Sort joints
                SortJoints(ref Result, ParentStack, Cosmetic);

                // Pre-fetch skins
                var SkinClusters = GetSkinClusters();
                var BoneMapping  = Result.GetBoneMapping();

                // A list of used materials
                int MaterialIndex = 0;
                var UsedMaterials = new Dictionary <string, int>();
                var UsedMeshes    = new HashSet <string>();

                // Iterate and add meshes
                foreach (var Mesh in ExportObjectList.DependNodes(MFn.Type.kMesh))
                {
                    // Step
                    MayaCfg.StepProgress();

                    // Grab the controller
                    var Path = GetObjectDagPath(Mesh);
                    Path.extendToShape();
                    var Controller = new MFnMesh(Path);

                    // Ignore duplicates
                    if (UsedMeshes.Contains(Path.partialPathName))
                    {
                        continue;
                    }
                    UsedMeshes.Add(Path.partialPathName);

                    // Pre-fetch materials
                    var MeshMaterials = GetMaterialsMesh(ref Controller, ref Path);
                    foreach (var Mat in MeshMaterials)
                    {
                        if (!UsedMaterials.ContainsKey(Mat.Name))
                        {
                            UsedMaterials.Add(Mat.Name, MaterialIndex++);
                            Result.Materials.Add(Mat);
                        }
                    }

                    // New mesh
                    var NewMesh = new Mesh();

                    // Grab iterators
                    var VertexIterator = new MItMeshVertex(Path);
                    var FaceIterator   = new MItMeshPolygon(Path);

                    // Get the cluster for this
                    var SkinCluster = FindSkinCluster(ref SkinClusters, Controller);
                    var SkinJoints  = new MDagPathArray();

                    if (SkinCluster != null)
                    {
                        SkinCluster.influenceObjects(SkinJoints);
                    }

                    // Build vertex array
                    for (; !VertexIterator.isDone; VertexIterator.next())
                    {
                        // Prepare
                        var NewVert = new Vertex();

                        // Grab data
                        NewVert.Position = VertexIterator.position(MSpace.Space.kWorld) * (1 / 2.54);

                        // Weights if valid
                        if (SkinCluster != null)
                        {
                            var WeightValues = new MDoubleArray();

                            uint Influence = 0;
                            SkinCluster.getWeights(Path, VertexIterator.currentItem(), WeightValues, ref Influence);

                            for (int i = 0; i < (int)WeightValues.length; i++)
                            {
                                if (WeightValues[i] < 0.000001)
                                {
                                    continue;
                                }
                                var WeightTagName = CleanNodeName(SkinJoints[i].partialPathName);
                                var WeightID      = (BoneMapping.ContainsKey(WeightTagName)) ? BoneMapping[WeightTagName] : 0;

                                NewVert.Weights.Add(new Tuple <int, float>(WeightID, (float)WeightValues[i]));
                            }
                        }
                        if (NewVert.Weights.Count == 0)
                        {
                            NewVert.Weights.Add(new Tuple <int, float>(0, 1.0f));
                        }

                        // Add it
                        NewMesh.Vertices.Add(NewVert);
                    }

                    // Build face array
                    for (; !FaceIterator.isDone; FaceIterator.next())
                    {
                        var Indices = new MIntArray();
                        var Normals = new MVectorArray();
                        var UVUs    = new MFloatArray();
                        var UVVs    = new MFloatArray();

                        FaceIterator.getVertices(Indices);
                        FaceIterator.getNormals(Normals, MSpace.Space.kWorld);
                        FaceIterator.getUVs(UVUs, UVVs);

                        // Only support TRIS/QUAD
                        if (Indices.Count < 3)
                        {
                            continue;
                        }

                        if (Indices.Count == 3)
                        {
                            // Create new face
                            var NewFace = new FaceVertex();
                            // Setup
                            NewFace.Indices[0] = Indices[0];
                            NewFace.Indices[2] = Indices[1];
                            NewFace.Indices[1] = Indices[2];

                            // Normals
                            NewFace.Normals[0] = new MVector(Normals[0][0], Normals[0][1], Normals[0][2]);
                            NewFace.Normals[2] = new MVector(Normals[1][0], Normals[1][1], Normals[1][2]);
                            NewFace.Normals[1] = new MVector(Normals[2][0], Normals[2][1], Normals[2][2]);

                            // Colors
                            FaceIterator.getColor(NewFace.Colors[0], 0);
                            FaceIterator.getColor(NewFace.Colors[2], 1);
                            FaceIterator.getColor(NewFace.Colors[1], 2);

                            // Append UV Layers
                            NewFace.UVs[0] = new Tuple <float, float>(UVUs[0], 1 - UVVs[0]);
                            NewFace.UVs[2] = new Tuple <float, float>(UVUs[1], 1 - UVVs[1]);
                            NewFace.UVs[1] = new Tuple <float, float>(UVUs[2], 1 - UVVs[2]);

                            // Set material index
                            if (MeshMaterials.Count > 0)
                            {
                                NewFace.MaterialIndex = UsedMaterials[MeshMaterials[0].Name];
                            }

                            // Add it
                            NewMesh.Faces.Add(NewFace);
                        }
                        else
                        {
                            // Create new faces
                            FaceVertex NewFace = new FaceVertex(), NewFace2 = new FaceVertex();
                            // Setup
                            NewFace.Indices[0]  = Indices[0];
                            NewFace.Indices[2]  = Indices[1];
                            NewFace.Indices[1]  = Indices[2];
                            NewFace2.Indices[0] = Indices[0];
                            NewFace2.Indices[2] = Indices[2];
                            NewFace2.Indices[1] = Indices[3];

                            // Normals
                            NewFace.Normals[0]  = new MVector(Normals[0][0], Normals[0][1], Normals[0][2]);
                            NewFace.Normals[2]  = new MVector(Normals[1][0], Normals[1][1], Normals[1][2]);
                            NewFace.Normals[1]  = new MVector(Normals[2][0], Normals[2][1], Normals[2][2]);
                            NewFace2.Normals[0] = new MVector(Normals[0][0], Normals[0][1], Normals[0][2]);
                            NewFace2.Normals[2] = new MVector(Normals[2][0], Normals[2][1], Normals[2][2]);
                            NewFace2.Normals[1] = new MVector(Normals[3][0], Normals[3][1], Normals[3][2]);

                            // Colors
                            FaceIterator.getColor(NewFace.Colors[0], 0);
                            FaceIterator.getColor(NewFace.Colors[2], 1);
                            FaceIterator.getColor(NewFace.Colors[1], 2);
                            FaceIterator.getColor(NewFace2.Colors[0], 0);
                            FaceIterator.getColor(NewFace2.Colors[2], 2);
                            FaceIterator.getColor(NewFace2.Colors[1], 3);

                            // Append UV Layers
                            NewFace.UVs[0]  = new Tuple <float, float>(UVUs[0], 1 - UVVs[0]);
                            NewFace.UVs[2]  = new Tuple <float, float>(UVUs[1], 1 - UVVs[1]);
                            NewFace.UVs[1]  = new Tuple <float, float>(UVUs[2], 1 - UVVs[2]);
                            NewFace2.UVs[0] = new Tuple <float, float>(UVUs[0], 1 - UVVs[0]);
                            NewFace2.UVs[2] = new Tuple <float, float>(UVUs[2], 1 - UVVs[2]);
                            NewFace2.UVs[1] = new Tuple <float, float>(UVUs[3], 1 - UVVs[3]);

                            // Set material index
                            if (MeshMaterials.Count > 0)
                            {
                                NewFace.MaterialIndex  = UsedMaterials[MeshMaterials[0].Name];
                                NewFace2.MaterialIndex = UsedMaterials[MeshMaterials[0].Name];
                            }

                            // Add it
                            NewMesh.Faces.Add(NewFace);
                            NewMesh.Faces.Add(NewFace2);
                        }
                    }

                    // Add it
                    Result.Meshes.Add(NewMesh);
                }

                // Write
                switch (FileType)
                {
                case XModelType.Export:
                    Result.WriteExport(FilePath);
                    break;

                case XModelType.Bin:
                    Result.WriteBin(FilePath);
                    break;
                }
            }

            // Log complete
            MGlobal.displayInfo(string.Format("[CODTools] Exported {0}", System.IO.Path.GetFileName(FilePath)));
        }
        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");
        }