/// <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 maTranslator() { fBrokenConnSrcs = new MPlugArray(); fBrokenConnDests = new MPlugArray(); fDefaultNodes = new MObjectArray(); fInstanceChildren = new MDagPathArray(); fInstanceParents = new MDagPathArray(); fParentingRequired = new MDagPathArray(); }
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 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))); }
/// <summary> /// Faces and vertices UVs, positions and normals. /// </summary> private static void ExtractMeshGeometry(MayaM2Mesh mesh, MDagPath meshPath, Dictionary <string, MayaM2Bone> jointMap, List <MayaM2Vertex> globalVertexList) { // ***Data Tables*** // UV Sets var uvsets = new MStringArray(); var meshFunctions = new MFnMesh(meshPath); meshFunctions.getUVSetNames(uvsets); //Bone Weights var vertexWeights = new List <MDoubleArray>(); var influenceObjects = new MDagPathArray(); GetMeshWeightData(vertexWeights, influenceObjects, meshPath); //Positions var positions = new MFloatPointArray(); meshFunctions.getPoints(positions, MSpace.Space.kWorld); //Normals var normals = new MFloatVectorArray(); meshFunctions.getVertexNormals(false, normals, MSpace.Space.kWorld); var polygonIter = new MItMeshPolygon(meshPath); while (!polygonIter.isDone) { //Divide face into triangles var polyMeshRelative = new MIntArray(); polygonIter.getVertices(polyMeshRelative); int numTriangles; polygonIter.numTriangles(out numTriangles); for (var i = 0; i < numTriangles; i++) { var triangle = new MayaM2Triangle(); var triangleMeshRelative = new MIntArray(); polygonIter.getTriangle(i, new MPointArray(), triangleMeshRelative); var triangleFaceRelative = GetLocalTriangle(polyMeshRelative, triangleMeshRelative); for (var v = 0; v < 3; v++) { var meshIndex = triangleMeshRelative[v]; var faceIndex = triangleFaceRelative[v]; //Bone weights var weights = new List <Tuple <MayaM2Bone, double> >(); for (var b = 0; b < influenceObjects.length; b++) //for each joint { var kJointPath = influenceObjects[b]; if (!kJointPath.hasFn(MFn.Type.kJoint)) { continue; } Debug.Assert(b < vertexWeights[meshIndex].Count, "vertexWeights size : " + vertexWeights.Count + " " + "\njointWeights for this vertex : " + vertexWeights[meshIndex].Count); //Here are a joint&weight for this vertex if (vertexWeights[meshIndex][b] > Epsilon) { weights.Add(new Tuple <MayaM2Bone, double>(jointMap[kJointPath.fullPathName], vertexWeights[meshIndex][b])); } } //Position & normals var position = positions[(int)polygonIter.vertexIndex(faceIndex)]; var normal = normals[(int)polygonIter.normalIndex(faceIndex)]; //UV coordinates var uvCoordinates = new List <Tuple <float, float> >(); if (uvsets.length > 0 && meshFunctions.numUVs(uvsets[0]) > 0) { foreach (var uvset in uvsets) { var uvCoords = new float[2]; polygonIter.getUV(faceIndex, uvCoords, uvset); uvCoordinates.Add(new Tuple <float, float>(uvCoords[0], uvCoords[1])); } } var vert = VertexFactory.Create(position, normal, uvCoordinates, weights, globalVertexList); triangle.Vertices.Add(vert); } mesh.Faces.Add(triangle); } polygonIter.next(); } }
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(); } }
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"); }
public exampleCameraSetViewCmd() { fCameraList = new MDagPathArray(); }
public exampleCameraSetViewCmd() { fCameraList = new MDagPathArray(); }
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; }