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