public override void writeDoubleVectorArray(MVectorArray 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(doubleVectorArrayTag); myCurrentChanelNode.AppendChild(arrayNode); for (int i = 0; i < size; i++) { MVector value = array[i]; XmlNode valueNode = myXmlDoc.CreateElement("value"); arrayNode.AppendChild(valueNode); XmlNode xValueNode = myXmlDoc.CreateElement("x"); xValueNode.InnerText = Convert.ToString(value.x); valueNode.AppendChild(xValueNode); XmlNode yValueNode = myXmlDoc.CreateElement("y"); yValueNode.InnerText = Convert.ToString(value.y); valueNode.AppendChild(yValueNode); XmlNode zValueNode = myXmlDoc.CreateElement("z"); zValueNode.InnerText = Convert.ToString(value.z); valueNode.AppendChild(zValueNode); } } return; }
public override void readDoubleVectorArray(MVectorArray array, uint arraySize) { Trace.Assert(myCurrentChanelNode != null); XmlNode doubleVectorArrayNode = myCurrentChanelNode.SelectSingleNode(doubleVectorArrayTag); XmlNodeList valueNodeList = doubleVectorArrayNode.SelectNodes("value"); uint i = 0; array.clear(); array.length = arraySize; foreach (XmlNode valueNode in valueNodeList) { XmlNode xNode = valueNode.SelectSingleNode("x"); double valueX = Convert.ToDouble(xNode.InnerText); XmlNode yNode = valueNode.SelectSingleNode("y"); double valuey = Convert.ToDouble(yNode.InnerText); XmlNode zNode = valueNode.SelectSingleNode("z"); double valuez = Convert.ToDouble(zNode.InnerText); MVector v = new MVector(valueX, valuey, valuez); array.set(v, i); i++; } return; }
public apiMeshGeom() { vertices = new MPointArray(); face_counts = new MIntArray(); face_connects = new MIntArray(); normals = new MVectorArray(); uvcoords = new apiMeshGeomUV(); faceCount = 0; }
public static List <object> MelCommand(string MelCommand) { MStringArray stringResults = new MStringArray(); MIntArray intResults = new MIntArray(); MDoubleArray doubleResults = new MDoubleArray(); MVectorArray vectorResults = new MVectorArray(); List <object> results = new List <object>(); MCommandResult mcr = new MCommandResult(); MDagPath dag = new MDagPath(); try { MGlobal.executeCommand(MelCommand, mcr); // MGlobal.executeCommand(MelCommand, stringResults); } catch (MemberAccessException e) { MGlobal.displayWarning(e.Message); } switch (mcr.resultType) { case MCommandResult.Type.kStringArray: mcr.getResult(stringResults); results.AddRange(stringResults); break; case MCommandResult.Type.kIntArray: mcr.getResult(intResults); results.AddRange(intResults.Cast <object>()); break; case MCommandResult.Type.kDoubleArray: mcr.getResult(doubleResults); results.AddRange(doubleResults.Cast <object>()); break; case MCommandResult.Type.kVectorArray: mcr.getResult(vectorResults); results.AddRange(vectorResults.Cast <object>()); break; default: mcr.getResult(stringResults); results.AddRange(stringResults); break; } mcr.Dispose(); return(results); }
// // Description // // Constructs a cube // public void buildCube(double cube_size, MPointArray pa, MIntArray faceCounts, MIntArray faceConnects, MVectorArray normals, apiMeshGeomUV uvs) { const int num_faces = 6; const int num_face_connects = 24; const double normal_value = 0.5775; const int uv_count = 14; pa.clear(); faceCounts.clear(); faceConnects.clear(); uvs.reset(); pa.append(new MPoint(-cube_size, -cube_size, -cube_size)); pa.append(new MPoint(cube_size, -cube_size, -cube_size)); pa.append(new MPoint(cube_size, -cube_size, cube_size)); pa.append(new MPoint(-cube_size, -cube_size, cube_size)); pa.append(new MPoint(-cube_size, cube_size, -cube_size)); pa.append(new MPoint(-cube_size, cube_size, cube_size)); pa.append(new MPoint(cube_size, cube_size, cube_size)); pa.append(new MPoint(cube_size, cube_size, -cube_size)); normals.append(new MVector(-normal_value, -normal_value, -normal_value)); normals.append(new MVector(normal_value, -normal_value, -normal_value)); normals.append(new MVector(normal_value, -normal_value, normal_value)); normals.append(new MVector(-normal_value, -normal_value, normal_value)); normals.append(new MVector(-normal_value, normal_value, -normal_value)); normals.append(new MVector(-normal_value, normal_value, normal_value)); normals.append(new MVector(normal_value, normal_value, normal_value)); normals.append(new MVector(normal_value, normal_value, -normal_value)); // Define the UVs for the cube. // float[] uv_pts = new float[uv_count * 2] { 0.375f, 0.0f, 0.625f, 0.0f, 0.625f, 0.25f, 0.375f, 0.25f, 0.625f, 0.5f, 0.375f, 0.5f, 0.625f, 0.75f, 0.375f, 0.75f, 0.625f, 1.0f, 0.375f, 1.0f, 0.875f, 0.0f, 0.875f, 0.25f, 0.125f, 0.0f, 0.125f, 0.25f }; // UV Face Vertex Id. // int[] uv_fvid = new int[num_face_connects] { 0, 1, 2, 3, 3, 2, 4, 5, 5, 4, 6, 7, 7, 6, 8, 9, 1, 10, 11, 2, 12, 0, 3, 13 }; int i; for (i = 0; i < uv_count; i++) { uvs.append_uv(uv_pts[i * 2], uv_pts[i * 2 + 1]); } for (i = 0; i < num_face_connects; i++) { uvs.faceVertexIndex.append(uv_fvid[i]); } // Set up an array containing the number of vertices // for each of the 6 cube faces (4 vertices per face) // int[] face_counts = new int[num_faces] { 4, 4, 4, 4, 4, 4 }; for (i = 0; i < num_faces; i++) { faceCounts.append(face_counts[i]); } // Set up and array to assign vertices from pa to each face // int[] face_connects = new int[num_face_connects] { 0, 1, 2, 3, 4, 5, 6, 7, 3, 2, 6, 5, 0, 3, 5, 4, 0, 4, 7, 1, 1, 7, 6, 2 }; for (i = 0; i < num_face_connects; i++) { faceConnects.append(face_connects[i]); } }
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; }
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))); }
// Support the move tools normal/u/v mode (components) // public override bool vertexOffsetDirection( MObject component, MVectorArray direction, MVertexOffsetMode mode, bool normalize ) // // Description // // Returns offsets for the given components to be used my the // move tool in normal/u/v mode. // // Arguments // // component - components to calculate offsets for // direction - array of offsets to be filled // mode - the type of offset to be calculated // normalize - specifies whether the offsets should be normalized // // Returns // // true if the offsets could be calculated, false otherwise // { bool offsetOkay = false ; MFnSingleIndexedComponent fnComp = new MFnSingleIndexedComponent( component ); if ( component.apiType != MFn.Type.kMeshVertComponent ) { return false; } offsetOkay = true ; apiMeshGeom geomPtr = meshGeom(); if ( null == geomPtr ) { return false; } // For each vertex add the appropriate offset // int count = fnComp.elementCount; for ( int idx=0; idx<count; idx++ ) { MVector normal = geomPtr.normals[ fnComp.element(idx) ]; if( mode == MVertexOffsetMode.kNormal ) { if( normalize ) normal.normalize() ; direction.append( normal ); } else { // Construct an orthonormal basis from the normal // uAxis, and vAxis are the new vectors. // MVector uAxis = new MVector(); MVector vAxis = new MVector(); uint i, j, k; double a; normal.normalize(); i = 0; a = Math.Abs( normal[0] ); if ( a < Math.Abs(normal[1]) ) { i = 1; a = Math.Abs(normal[1]); } if ( a < Math.Abs(normal[2]) ) { i = 2; } j = (i+1)%3; k = (j+1)%3; a = Math.Sqrt(normal[i]*normal[i] + normal[j]*normal[j]); uAxis[i] = -normal[j]/a; uAxis[j] = normal[i]/a; uAxis[k] = 0.0; vAxis = normal.crossProduct( uAxis ); if ( mode == MVertexOffsetMode.kUTangent || mode == MVertexOffsetMode.kUVNTriad ) { if( normalize ) uAxis.normalize() ; direction.append( uAxis ); } if ( mode == MVertexOffsetMode.kVTangent || mode == MVertexOffsetMode.kUVNTriad ) { if( normalize ) vAxis.normalize() ; direction.append( vAxis ); } if ( mode == MVertexOffsetMode.kUVNTriad ) { if( normalize ) normal.normalize() ; direction.append( normal ); } } } return offsetOkay; }
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 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 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); } } }
// // Description // // Create circles of vertices starting with // the top pole ending with the bottom pole // public void buildSphere(double rad, int div, MPointArray vertices, MIntArray counts, MIntArray connects, MVectorArray normals, apiMeshGeomUV uvs) { double u = -Math.PI / 2.0; double v = -Math.PI; double u_delta = Math.PI / ((double)div); double v_delta = 2 * Math.PI / ((double)div); MPoint topPole = new MPoint(0.0, rad, 0.0); MPoint botPole = new MPoint(0.0, -rad, 0.0); // Build the vertex and normal table // vertices.append(botPole); normals.append(botPole.minus(MPoint.origin)); int i; for (i = 0; i < (div - 1); i++) { u += u_delta; v = -Math.PI; for (int j = 0; j < div; j++) { double x = rad * Math.Cos(u) * Math.Cos(v); double y = rad * Math.Sin(u); double z = rad * Math.Cos(u) * Math.Sin(v); MPoint pnt = new MPoint(x, y, z); vertices.append(pnt); normals.append(pnt.minus(MPoint.origin)); v += v_delta; } } vertices.append(topPole); normals.append(topPole.minus(MPoint.origin)); // Create the connectivity lists // int vid = 1; int numV = 0; for (i = 0; i < div; i++) { for (int j = 0; j < div; j++) { if (i == 0) { counts.append(3); connects.append(0); connects.append(j + vid); connects.append((j == (div - 1)) ? vid : j + vid + 1); } else if (i == (div - 1)) { counts.append(3); connects.append(j + vid + 1 - div); connects.append(vid + 1); connects.append(j == (div - 1) ? vid + 1 - div : j + vid + 2 - div); } else { counts.append(4); connects.append(j + vid + 1 - div); connects.append(j + vid + 1); connects.append(j == (div - 1) ? vid + 1 : j + vid + 2); connects.append(j == (div - 1) ? vid + 1 - div : j + vid + 2 - div); } numV++; } vid = numV; } // TODO: Define UVs for sphere ... // }
public void drawVertices(MDrawRequest request, M3dView view) { MDrawData data = request.drawData(); MVectorArray geom = data.geometry() as MVectorArray; view.beginGL(); // Query current state so it can be restored // bool lightingWasOn = OpenGL.glIsEnabled(OpenGL.GL_LIGHTING) != 0 ? true : false; if (lightingWasOn) { OpenGL.glDisable(OpenGL.GL_LIGHTING); } float lastPointSize; getLastPointSize(out lastPointSize); // Set the point size of the vertices // OpenGL.glPointSize(POINT_SIZE); // If there is a component specified by the draw request // then loop over comp (using an MFnComponent class) and draw the // active vertices, otherwise draw all vertices. // MObject comp = request.component; if (!comp.isNull) { MFnSingleIndexedComponent fnComponent = new MFnSingleIndexedComponent(comp); for (int i = 0; i < fnComponent.elementCount; i++) { int index = fnComponent.element(i); OpenGL.glBegin(OpenGL.GL_POINTS); MVector point = geom[index]; OpenGL.glVertex3f((float)point[0], (float)point[1], (float)point[2]); OpenGL.glEnd(); MPoint mp = new MPoint(point); view.drawText(String.Format("{0}", index), mp); } } else { for (int i = 0; i < geom.length; i++) { OpenGL.glBegin(OpenGL.GL_POINTS); MVector point = geom[i]; OpenGL.glVertex3f((float)point[0], (float)point[1], (float)point[2]); OpenGL.glEnd(); } } // Restore the state // if (lightingWasOn) { OpenGL.glEnable(OpenGL.GL_LIGHTING); } OpenGL.glPointSize(lastPointSize); view.endGL(); }
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 bool selectVertices(MSelectInfo selectInfo, MSelectionList selectionList, MPointArray worldSpaceSelectPts) { bool selected = false; M3dView view = selectInfo.view; MPoint xformedPoint; MPoint currentPoint = new MPoint(); MPoint selectionPoint = new MPoint(); double z, previousZ = 0.0; int closestPointVertexIndex = -1; MDagPath path = selectInfo.multiPath; // Create a component that will store the selected vertices // MFnSingleIndexedComponent fnComponent = new MFnSingleIndexedComponent(); MObject surfaceComponent = fnComponent.create(MFn.Type.kMeshVertComponent); int vertexIndex; // if the user did a single mouse click and we find > 1 selection // we will use the alignmentMatrix to find out which is the closest // MMatrix alignmentMatrix = new MMatrix(); MPoint singlePoint = new MPoint(); bool singleSelection = selectInfo.singleSelection; if (singleSelection) { alignmentMatrix = selectInfo.alignmentMatrix; } // Get the geometry information // apiSimpleShape shape = surfaceShape as apiSimpleShape; MVectorArray geom = shape.controlPoints; // Loop through all vertices of the mesh and // see if they lie withing the selection area // int numVertices = (int)geom.length; for (vertexIndex = 0; vertexIndex < numVertices; vertexIndex++) { MVector point = geom[vertexIndex]; // Sets OpenGL's render mode to select and stores // selected items in a pick buffer // view.beginSelect(); OpenGL.glBegin(OpenGL.GL_POINTS); OpenGL.glVertex3f((float)point[0], (float)point[1], (float)point[2]); OpenGL.glEnd(); if (view.endSelect() > 0) // Hit count > 0 { selected = true; if (singleSelection) { xformedPoint = currentPoint; xformedPoint.homogenize(); xformedPoint = xformedPoint.multiply(alignmentMatrix); z = xformedPoint.z; if (closestPointVertexIndex < 0 || z > previousZ) { closestPointVertexIndex = vertexIndex; singlePoint = currentPoint; previousZ = z; } } else { // multiple selection, store all elements // fnComponent.addElement(vertexIndex); } } } // If single selection, insert the closest point into the array // if (selected && selectInfo.singleSelection) { fnComponent.addElement(closestPointVertexIndex); // need to get world space position for this vertex // selectionPoint = singlePoint; selectionPoint = selectionPoint.multiply(path.inclusiveMatrix); } // Add the selected component to the selection list // if (selected) { MSelectionList selectionItem = new MSelectionList(); selectionItem.add(path, surfaceComponent); MSelectionMask mask = new MSelectionMask(MSelectionMask.SelectionType.kSelectComponentsMask); selectInfo.addSelection( selectionItem, selectionPoint, selectionList, worldSpaceSelectPts, mask, true); } return(selected); }
public override void getDrawRequests(MDrawInfo info, bool objectAndActiveOnly, MDrawRequestQueue queue) { apiSimpleShape shapeNode = surfaceShape as apiSimpleShape; if (shapeNode == null) { return; } // This call creates a prototype draw request that we can fill // in and then add to the draw queue. // MDrawRequest request = info.getPrototype(this); MDrawData data; MVectorArray geomPtr = shapeNode.controlPoints; // Stuff our data into the draw request, it'll be used when the drawing // actually happens getDrawData(geomPtr, out data); request.setDrawData(data); // Decode the draw info and determine what needs to be drawn // M3dView.DisplayStyle appearance = info.displayStyle; M3dView.DisplayStatus displayStatus = info.displayStatus; switch (appearance) { case M3dView.DisplayStyle.kWireFrame: { request.token = (int)DrawShapeStyle.kDrawWireframe; M3dView.ColorTable activeColorTable = M3dView.ColorTable.kActiveColors; M3dView.ColorTable dormantColorTable = M3dView.ColorTable.kDormantColors; switch (displayStatus) { case M3dView.DisplayStatus.kLead: request.setColor(LEAD_COLOR, (int)activeColorTable); break; case M3dView.DisplayStatus.kActive: request.setColor(ACTIVE_COLOR, (int)activeColorTable); break; case M3dView.DisplayStatus.kActiveAffected: request.setColor(ACTIVE_AFFECTED_COLOR, (int)activeColorTable); break; case M3dView.DisplayStatus.kDormant: request.setColor(DORMANT_COLOR, (int)dormantColorTable); break; case M3dView.DisplayStatus.kHilite: request.setColor(HILITE_COLOR, (int)activeColorTable); break; default: break; } queue.add(request); break; } case M3dView.DisplayStyle.kGouraudShaded: { // Create the smooth shaded draw request // request.token = (int)DrawShapeStyle.kDrawSmoothShaded; // Need to get the material info // MDagPath path = info.multiPath; // path to your dag object M3dView view = info.view; // view to draw to MMaterial material = base.material(path); // Evaluate the material and if necessary, the texture. // material.evaluateMaterial(view, path); bool drawTexture = true; if (drawTexture && material.materialIsTextured) { material.evaluateTexture(data); } request.material = material; bool materialTransparent = false; material.getHasTransparency(ref materialTransparent); if (materialTransparent) { request.isTransparent = true; } queue.add(request); // create a draw request for wireframe on shaded if // necessary. // if ((displayStatus == M3dView.DisplayStatus.kActive) || (displayStatus == M3dView.DisplayStatus.kLead) || (displayStatus == M3dView.DisplayStatus.kHilite)) { MDrawRequest wireRequest = request; wireRequest.setDrawData(data); wireRequest.token = (int)DrawShapeStyle.kDrawWireframeOnShaded; wireRequest.displayStyle = M3dView.DisplayStyle.kWireFrame; M3dView.ColorTable activeColorTable = M3dView.ColorTable.kActiveColors; switch (displayStatus) { case M3dView.DisplayStatus.kLead: wireRequest.setColor(LEAD_COLOR, (int)activeColorTable); break; case M3dView.DisplayStatus.kActive: wireRequest.setColor(ACTIVE_COLOR, (int)activeColorTable); break; case M3dView.DisplayStatus.kHilite: wireRequest.setColor(HILITE_COLOR, (int)activeColorTable); break; default: break; } queue.add(wireRequest); } break; } case M3dView.DisplayStyle.kFlatShaded: request.token = (int)DrawShapeStyle.kDrawFlatShaded; break; default: break; } // Add draw requests for components // if (!objectAndActiveOnly) { // Inactive components // if ((appearance == M3dView.DisplayStyle.kPoints) || (displayStatus == M3dView.DisplayStatus.kHilite)) { MDrawRequest vertexRequest = request; vertexRequest.setDrawData(data); vertexRequest.token = (int)DrawShapeStyle.kDrawVertices; vertexRequest.setColor(DORMANT_VERTEX_COLOR, (int)M3dView.ColorTable.kActiveColors); queue.add(vertexRequest); } // Active components // if (shapeNode.hasActiveComponents) { MDrawRequest activeVertexRequest = request; activeVertexRequest.setDrawData(data); activeVertexRequest.token = (int)DrawShapeStyle.kDrawVertices; activeVertexRequest.setColor(ACTIVE_VERTEX_COLOR, (int)M3dView.ColorTable.kActiveColors); MObjectArray clist = shapeNode.activeComponents; MObject vertexComponent = clist[0]; // Should filter list activeVertexRequest.component = vertexComponent; queue.add(activeVertexRequest); } } }
public apiSimpleShapeIterator(object userGeometry, MObject components) : base(userGeometry, components) { mGeometry = userGeometry as MVectorArray; reset(); }
// // Description // // This function takes an input surface of type kMeshData and converts // the geometry into this nodes attributes. // Returns false if nothing is connected. // public bool computeInputMesh(MPlug plug, MDataBlock datablock, MPointArray vertices, MIntArray counts, MIntArray connects, MVectorArray normals, apiMeshGeomUV uvs) { // Get the input subdiv // MDataHandle inputData = datablock.inputValue( inputMesh ); MObject surf = inputData.asMesh; // Check if anything is connected // MObject thisObj = thisMObject(); MPlug surfPlug = new MPlug( thisObj, inputMesh ); if ( !surfPlug.isConnected ) { datablock.setClean( plug ); return false; } // Extract the mesh data // MFnMesh surfFn = new MFnMesh(surf); surfFn.getPoints( vertices, MSpace.Space.kObject ); // Check to see if we have UVs to copy. // bool hasUVs = surfFn.numUVsProperty > 0; surfFn.getUVs( uvs.ucoord, uvs.vcoord ); for ( int i=0; i<surfFn.numPolygons; i++ ) { MIntArray polyVerts = new MIntArray(); surfFn.getPolygonVertices( i, polyVerts ); int pvc = (int)polyVerts.length; counts.append( pvc ); int uvId; for ( int v=0; v<pvc; v++ ) { if ( hasUVs ) { surfFn.getPolygonUVid( i, v, out uvId ); uvs.faceVertexIndex.append( uvId ); } connects.append( polyVerts[v] ); } } for ( int n=0; n<(int)vertices.length; n++ ) { MVector normal = new MVector(); surfFn.getVertexNormal( n, normal ); normals.append( normal ); } return true; }
// // 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); } } }
// // Description // // Constructs a cube // public void buildCube(double cube_size, MPointArray pa, MIntArray faceCounts, MIntArray faceConnects, MVectorArray normals, apiMeshGeomUV uvs) { const int num_faces = 6; const int num_face_connects = 24; const double normal_value = 0.5775; const int uv_count = 14; pa.clear(); faceCounts.clear(); faceConnects.clear(); uvs.reset(); pa.append( new MPoint( -cube_size, -cube_size, -cube_size ) ); pa.append( new MPoint( cube_size, -cube_size, -cube_size ) ); pa.append( new MPoint( cube_size, -cube_size, cube_size ) ); pa.append( new MPoint( -cube_size, -cube_size, cube_size ) ); pa.append( new MPoint( -cube_size, cube_size, -cube_size ) ); pa.append( new MPoint( -cube_size, cube_size, cube_size ) ); pa.append( new MPoint( cube_size, cube_size, cube_size ) ); pa.append( new MPoint( cube_size, cube_size, -cube_size ) ); normals.append( new MVector( -normal_value, -normal_value, -normal_value ) ); normals.append( new MVector( normal_value, -normal_value, -normal_value ) ); normals.append( new MVector( normal_value, -normal_value, normal_value ) ); normals.append( new MVector( -normal_value, -normal_value, normal_value ) ); normals.append( new MVector( -normal_value, normal_value, -normal_value ) ); normals.append( new MVector( -normal_value, normal_value, normal_value ) ); normals.append( new MVector( normal_value, normal_value, normal_value ) ); normals.append( new MVector( normal_value, normal_value, -normal_value ) ); // Define the UVs for the cube. // float[] uv_pts = new float[uv_count*2] { 0.375f, 0.0f, 0.625f, 0.0f, 0.625f, 0.25f, 0.375f, 0.25f, 0.625f, 0.5f, 0.375f, 0.5f, 0.625f, 0.75f, 0.375f, 0.75f, 0.625f, 1.0f, 0.375f, 1.0f, 0.875f, 0.0f, 0.875f, 0.25f, 0.125f, 0.0f, 0.125f, 0.25f }; // UV Face Vertex Id. // int[] uv_fvid = new int[num_face_connects]{ 0, 1, 2, 3, 3, 2, 4, 5, 5, 4, 6, 7, 7, 6, 8, 9, 1, 10, 11, 2, 12, 0, 3, 13 }; int i; for ( i = 0; i < uv_count; i ++ ) { uvs.append_uv( uv_pts[i*2], uv_pts[i*2 + 1] ); } for ( i = 0; i < num_face_connects; i ++ ) { uvs.faceVertexIndex.append( uv_fvid[i] ); } // Set up an array containing the number of vertices // for each of the 6 cube faces (4 vertices per face) // int[] face_counts = new int[num_faces]{ 4, 4, 4, 4, 4, 4 }; for ( i=0; i<num_faces; i++ ) { faceCounts.append( face_counts[i] ); } // Set up and array to assign vertices from pa to each face // int[] face_connects = new int[ num_face_connects ]{ 0, 1, 2, 3, 4, 5, 6, 7, 3, 2, 6, 5, 0, 3, 5, 4, 0, 4, 7, 1, 1, 7, 6, 2 }; for ( i=0; i<num_face_connects; i++ ) { faceConnects.append( face_connects[i] ); } }
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); } } }
// // Description // // Create circles of vertices starting with // the top pole ending with the bottom pole // public void buildSphere(double rad, int div, MPointArray vertices, MIntArray counts, MIntArray connects, MVectorArray normals, apiMeshGeomUV uvs) { double u = -Math.PI / 2.0; double v = -Math.PI; double u_delta = Math.PI / ((double)div); double v_delta = 2 * Math.PI / ((double)div); MPoint topPole = new MPoint( 0.0, rad, 0.0 ); MPoint botPole = new MPoint( 0.0, -rad, 0.0 ); // Build the vertex and normal table // vertices.append( botPole ); normals.append( botPole.minus(MPoint.origin) ); int i; for ( i=0; i<(div-1); i++ ) { u += u_delta; v = -Math.PI; for ( int j=0; j<div; j++ ) { double x = rad * Math.Cos(u) * Math.Cos(v); double y = rad * Math.Sin(u); double z = rad * Math.Cos(u) * Math.Sin(v) ; MPoint pnt = new MPoint( x, y, z ); vertices.append( pnt ); normals.append( pnt.minus(MPoint.origin) ); v += v_delta; } } vertices.append( topPole ); normals.append( topPole.minus(MPoint.origin) ); // Create the connectivity lists // int vid = 1; int numV = 0; for ( i=0; i<div; i++ ) { for ( int j=0; j<div; j++ ) { if ( i==0 ) { counts.append( 3 ); connects.append( 0 ); connects.append( j+vid ); connects.append( (j==(div-1)) ? vid : j+vid+1 ); } else if ( i==(div-1) ) { counts.append( 3 ); connects.append( j+vid+1-div ); connects.append( vid+1 ); connects.append( j==(div-1) ? vid+1-div : j+vid+2-div ); } else { counts.append( 4 ); connects.append( j + vid+1-div ); connects.append( j + vid+1 ); connects.append( j == (div-1) ? vid+1 : j+vid+2 ); connects.append( j == (div-1) ? vid+1-div : j+vid+2-div ); } numV++; } vid = numV; } // TODO: Define UVs for sphere ... // }
// // Description // // Returns offsets for the given components to be used my the // move tool in normal/u/v mode. // // Arguments // // component - components to calculate offsets for // direction - array of offsets to be filled // mode - the type of offset to be calculated // normalize - specifies whether the offsets should be normalized // // Returns // // true if the offsets could be calculated, false otherwise // // Support the move tools normal/u/v mode (components) // public override bool vertexOffsetDirection( MObject component, MVectorArray direction, MVertexOffsetMode mode, bool normalize) { bool offsetOkay = false ; MFnSingleIndexedComponent fnComp = new MFnSingleIndexedComponent( component ); if ( component.apiType != MFn.Type.kMeshVertComponent ) { return false; } offsetOkay = true ; apiMeshGeom geomPtr = meshGeom(); if ( null == geomPtr ) { return false; } // For each vertex add the appropriate offset // int count = fnComp.elementCount; for ( int idx=0; idx<count; idx++ ) { MVector normal = geomPtr.normals[ fnComp.element(idx) ]; if( mode == MVertexOffsetMode.kNormal ) { if( normalize ) normal.normalize() ; direction.append( normal ); } else { // Construct an orthonormal basis from the normal // uAxis, and vAxis are the new vectors. // MVector uAxis = new MVector(); MVector vAxis = new MVector(); uint i, j, k; double a; normal.normalize(); i = 0; a = Math.Abs( normal[0] ); if ( a < Math.Abs(normal[1]) ) { i = 1; a = Math.Abs(normal[1]); } if ( a < Math.Abs(normal[2]) ) { i = 2; } j = (i+1)%3; k = (j+1)%3; a = Math.Sqrt(normal[i]*normal[i] + normal[j]*normal[j]); uAxis[i] = -normal[j]/a; uAxis[j] = normal[i]/a; uAxis[k] = 0.0; vAxis = normal.crossProduct( uAxis ); if ( mode == MVertexOffsetMode.kUTangent || mode == MVertexOffsetMode.kUVNTriad ) { if( normalize ) uAxis.normalize() ; direction.append( uAxis ); } if ( mode == MVertexOffsetMode.kVTangent || mode == MVertexOffsetMode.kUVNTriad ) { if( normalize ) vAxis.normalize() ; direction.append( vAxis ); } if ( mode == MVertexOffsetMode.kUVNTriad ) { if( normalize ) normal.normalize() ; direction.append( normal ); } } } return offsetOkay; }
// // Description // // This function takes an input surface of type kMeshData and converts // the geometry into this nodes attributes. // Returns false if nothing is connected. // public bool computeInputMesh(MPlug plug, MDataBlock datablock, MPointArray vertices, MIntArray counts, MIntArray connects, MVectorArray normals, apiMeshGeomUV uvs) { // Get the input subdiv // MDataHandle inputData = datablock.inputValue(inputMesh); MObject surf = inputData.asMesh; // Check if anything is connected // MObject thisObj = thisMObject(); MPlug surfPlug = new MPlug(thisObj, inputMesh); if (!surfPlug.isConnected) { datablock.setClean(plug); return(false); } // Extract the mesh data // MFnMesh surfFn = new MFnMesh(surf); surfFn.getPoints(vertices, MSpace.Space.kObject); // Check to see if we have UVs to copy. // bool hasUVs = surfFn.numUVsProperty > 0; surfFn.getUVs(uvs.ucoord, uvs.vcoord); for (int i = 0; i < surfFn.numPolygons; i++) { MIntArray polyVerts = new MIntArray(); surfFn.getPolygonVertices(i, polyVerts); int pvc = (int)polyVerts.length; counts.append(pvc); int uvId; for (int v = 0; v < pvc; v++) { if (hasUVs) { surfFn.getPolygonUVid(i, v, out uvId); uvs.faceVertexIndex.append(uvId); } connects.append(polyVerts[v]); } } for (int n = 0; n < (int)vertices.length; n++) { MVector normal = new MVector(); surfFn.getVertexNormal(n, normal); normals.append(normal); } return(true); }