public apiMeshGeomIterator(object userGeometry, MObjectArray components) : base(userGeometry, components) { meshGeometry = (apiMeshGeom)userGeometry; reset(); }
/// <summary> /// Originally written in C++ by RobTheBloke. /// See https://nccastaff.bournemouth.ac.uk/jmacey/RobTheBloke/www/research/maya/mfnmesh.htm /// </summary> /// <param name="shadingEngine"></param> /// <returns>The shader name.</returns> private static MObjectArray GetMaterials(MObject shadingEngine) { // attach a function set to the shading engine var fn = new MFnDependencyNode(shadingEngine); // get access to the surfaceShader attribute. This will be connected to // lambert , phong nodes etc. var sShader = fn.findPlug("surfaceShader"); // will hold the connections to the surfaceShader attribute var materials = new MPlugArray(); // get the material connected to the surface shader sShader.connectedTo(materials, true, false); var materialsObjects = new MObjectArray(); if (materials.Count <= 0) { return(materialsObjects); } // if we found a material foreach (var plug in materials) { materialsObjects.Add(plug.node); } return(materialsObjects); }
private static List <Material> GetMaterialsMesh(ref MFnMesh Mesh, ref MDagPath Path) { // Get materials for this mesh var Result = new List <Material>(); // Fetch data var Shaders = new MObjectArray(); var ShaderIndices = new MIntArray(); Mesh.getConnectedShaders(Path.instanceNumber, Shaders, ShaderIndices); // Iterate and add for (int i = 0; i < (int)Shaders.length; i++) { // Find plug var ShaderNode = new MFnDependencyNode(Shaders[i]); var ShaderPlug = ShaderNode.findPlug("surfaceShader"); var MatPlug = new MPlugArray(); ShaderPlug.connectedTo(MatPlug, true, false); if (MatPlug.length > 0) { Result.Add(new Material(CleanNodeName(new MFnDependencyNode(MatPlug[0].node).name))); } } return(Result); }
public static ShapeData GetMaterialsOfDag(MDagPath dag) { if (dag == null) { Debug.Log("dag null"); } dag.extendToShape(); MFnDependencyNode dn = new MFnDependencyNode(dag.node); //Debug.Log(dn.absoluteName); //dn.findPlug("connectAttr pCubeShape3.instObjGroups[0] blinn2SG.dagSetMembers[1]"); MFnMesh mesh = new MFnMesh(dag); //int instanceCount = (int)shapeNode.instanceCount(false); //Debug.Log("dn instanceCount:" + instanceCount); uint instanceNumber = dag.instanceNumber; Debug.Log("dag instanceNumber:" + instanceNumber); MObjectArray sets = new MObjectArray(), comps = new MObjectArray(); mesh.getConnectedSetsAndMembers(instanceNumber, sets, comps, true); List <string> sgList = new List <string>(); for (int i = 0; i < sets.length; ++i) { MFnDependencyNode fnDepSGNode = new MFnDependencyNode(sets[i]); sgList.Add(fnDepSGNode.absoluteName); //Debug.Log(fnDepSGNode.name); } //Debug.Log("sgList Count:" + sgList.Count); return(new ShapeData(mesh, dag, sgList)); }
public maTranslator() { fBrokenConnSrcs = new MPlugArray(); fBrokenConnDests = new MPlugArray(); fDefaultNodes = new MObjectArray(); fInstanceChildren = new MDagPathArray(); fInstanceParents = new MDagPathArray(); fParentingRequired = new MDagPathArray(); }
public override MPxGeometryIterator geometryIteratorSetup(MObjectArray componentList, MObject components, bool forReadOnly) { apiSimpleShapeIterator result; if (components.isNull) { result = new apiSimpleShapeIterator(controlPoints, componentList); } else { result = new apiSimpleShapeIterator(controlPoints, components); } return result; }
////////////////////////////////////////////////////////////////// // // Overrides from MPxGeometryData // ////////////////////////////////////////////////////////////////// public override MPxGeometryIterator iterator( MObjectArray componentList, MObject component, bool useComponents) { apiMeshGeomIterator result = null; if ( useComponents ) { result = new apiMeshGeomIterator( fGeometry, componentList ); } else { result = new apiMeshGeomIterator( fGeometry, component ); } return result; }
public override MPxGeometryIterator geometryIteratorSetup(MObjectArray componentList, MObject components, bool forReadOnly) { apiSimpleShapeIterator result; if (components.isNull) { result = new apiSimpleShapeIterator(controlPoints, componentList); } else { result = new apiSimpleShapeIterator(controlPoints, components); } return(result); }
/// <summary> /// Extract all shaders (M2Batch) linked to a mesh. /// </summary> private static void ExtractMeshShaders(MayaM2Mesh mesh, MDagPath meshPath) { MGlobal.displayInfo("Looking for shaders in mesh " + meshPath.fullPathName); var meshFn = new MFnMesh(meshPath); // get the number of instances var numInstances = meshFn.parentCount; MGlobal.displayInfo("\t" + numInstances + " instances."); // loop through each instance of the mesh for (uint i = 0; i < numInstances; ++i) { // attach a function set to this instances parent transform //var fn = new MFnDependencyNode(fnMesh.parent(i)); // this will hold references to the shaders used on the meshes var shaderEngines = new MObjectArray(); // this is used to hold indices to the materials returned in the object array var faceIndices = new MIntArray(); // get the shaders used by the i'th mesh instance meshFn.getConnectedShaders(i, shaderEngines, faceIndices); switch (shaderEngines.length) { // if no shader applied to the mesh instance case 0: break; // if all faces use the same material case 1: var materials = GetMaterials(shaderEngines[0]); MGlobal.displayInfo("\t\tIn shaderEngine[0], found " + materials.length + " materials."); //TODO Extract Material data ExtractMaterial(mesh, materials[0]); //TODO Extract Transparency data //TODO Shader break; //Multiple materials, each applied only on some faces. default: throw new NotImplementedException("Cannot handle more than one shaderEngine per mesh."); } } }
////////////////////////////////////////////////////////////////// // // Overrides from MPxGeometryData // ////////////////////////////////////////////////////////////////// public override MPxGeometryIterator iterator(MObjectArray componentList, MObject component, bool useComponents) { apiMeshGeomIterator result = null; if (useComponents) { result = new apiMeshGeomIterator(fGeometry, componentList); } else { result = new apiMeshGeomIterator(fGeometry, component); } return(result); }
private void dumpInfo(MObject fileNode, MFnDependencyNode nodeFn, MObjectArray nodePath) { MObject fileAttr = nodeFn.attribute("fileTextureName"); MPlug plugToFile = new MPlug(fileNode, fileAttr); MFnDependencyNode dgFn = new MFnDependencyNode(); MGlobal.displayInfo("Name: " + nodeFn.name); MObject fnameValue = new MObject(); try { plugToFile.getValue(fnameValue); } catch (Exception) { MGlobal.displayInfo("error getting value from plug"); return; } MFnStringData stringFn = new MFnStringData(fnameValue); MGlobal.displayInfo("Texture: " + stringFn.stringProperty); string path = "Path: "; for (int i = (int)nodePath.length - 1; i >= 0; i--) { MObject currentNode = nodePath[i]; dgFn.setObject(currentNode); path += dgFn.name + "(" + dgFn.typeName + ")"; if (i > 0) { path += " -> "; } } MGlobal.displayInfo(path); }
public override void doIt(MArgList args) { MSelectionList list = new MSelectionList(); if ( args.length > 0 ) { // Arg list is > 0 so use objects that were passes in // uint last = args.length; for ( uint i = 0; i < last; i++ ) { // Attempt to find all of the objects matched // by the string and add them to the list // string argStr = args.asString(i); list.add(argStr); } } else { // Get arguments from Maya's selection list. MGlobal.getActiveSelectionList(list); } MObject node = new MObject(); MObjectArray nodePath = new MObjectArray(); MFnDependencyNode nodeFn = new MFnDependencyNode(); MFnDependencyNode dgNodeFnSet = new MFnDependencyNode(); for (MItSelectionList iter = new MItSelectionList(list); !iter.isDone; iter.next()) { iter.getDependNode(node); // // The following code shows how to navigate the DG manually without // using an iterator. First, find the attribute that you are // interested. Then connect a plug to it and see where the plug // connected to. Once you get all the connections, you can choose // which route you want to go. // // In here, we wanted to get to the nodes that instObjGroups connected // to since we know that the shadingEngine connects to the instObjGroup // attribute. // nodeFn.setObject( node ); MObject iogAttr = null; try { iogAttr = nodeFn.attribute("instObjGroups"); } catch (Exception) { MGlobal.displayInfo(nodeFn.name + ": is not a renderable object, skipping"); continue; } MPlug iogPlug = new MPlug(node, iogAttr); MPlugArray iogConnections = new MPlugArray(); // // instObjGroups is a multi attribute. In this example, just the // first connection will be tried. // if (!iogPlug.elementByLogicalIndex(0).connectedTo(iogConnections, false, true)) { MGlobal.displayInfo(nodeFn.name + ": is not in a shading group, skipping"); continue; } // // Now we would like to traverse the DG starting from the shadingEngine // since most likely all file texture nodes will be found. Note the // filter used to initialize the DG iterator. There are lots of filter // type available in MF.Type that you can choose to suite your needs. // bool foundATexture = false; for ( int i=0; i < iogConnections.length; i++ ) { MObject currentNode = iogConnections[i].node; // // Note that upon initialization, the current pointer of the // iterator already points to the first valid node. // MItDependencyGraph dgIt = new MItDependencyGraph(currentNode, MFn.Type.kFileTexture, MItDependencyGraph.Direction.kUpstream, MItDependencyGraph.Traversal.kBreadthFirst, MItDependencyGraph.Level.kNodeLevel); if (dgIt == null) { continue; } dgIt.disablePruningOnFilter(); for ( ; !dgIt.isDone; dgIt.next() ) { MObject thisNode = dgIt.thisNode(); dgNodeFnSet.setObject(thisNode); try { dgIt.getNodePath(nodePath); } catch (Exception) { MGlobal.displayInfo("getNodePath"); continue; } // // append the starting node. // nodePath.append(node); dumpInfo( thisNode, dgNodeFnSet, nodePath ); foundATexture = true; } } if ( !foundATexture ) { MGlobal.displayInfo(nodeFn.name + ": is not connected to a file texture"); } } return; }
public Material MakeMaterial(MFnMesh fnMesh) { MaterialGroup matGroup =new MaterialGroup () ; MObjectArray shaders =new MObjectArray() ; MIntArray indices =new MIntArray () ; fnMesh.getConnectedShaders (0, shaders, indices) ; for ( int i =0 ; i < shaders.length ; i++ ) { MFnDependencyNode shaderGroup =new MFnDependencyNode (shaders [i]) ; MPlug shaderPlug =shaderGroup.findPlug ("surfaceShader") ; MPlugArray connections =new MPlugArray () ; shaderPlug.connectedTo (connections, true, false) ; for ( int u =0 ; u < connections.length ; u++ ) { MFnDependencyNode depNode =new MFnDependencyNode (connections [u].node) ; //MPlug colorPlug =depNode.findPlug ("color") ; //MColor mcolor =new MColor () ; ///*MPlugArray cc =new MPlugArray () ; //colorPlug.connectedTo (cc, true , false) ; //if ( cc.length > 0 ) { // // Plug is driven by an input connection. // for ( int v =0 ; v < cc.length ; v++ ) { // MPlug color2Plug =cc [v] ; // Console.WriteLine (color2Plug.numChildren) ; // color2Plug.child (0).getValue (mcolor.r) ; // color2Plug.child (1).getValue (mcolor.g) ; // color2Plug.child (2).getValue (mcolor.b) ; // //color2Plug.child (3).getValue (mcolor.a) ; // } //} else {*/ // mcolor.r =colorPlug.child (0).asFloat () ; // mcolor.g =colorPlug.child (1).asFloat () ; // mcolor.b =colorPlug.child (2).asFloat () ; // //colorPlug.child (3).getValue (mcolor.a) ; ////} //MPlug trPlug =depNode.findPlug ("transparency") ; //float transparency =1.0f - trPlug.child (0).asFloat () ; ////return new DiffuseMaterial (new SolidColorBrush (Color.FromScRgb (transparency, mcolor.r, mcolor.g, mcolor.b))) ; //DiffuseMaterial diffuse =new DiffuseMaterial (new SolidColorBrush (Color.FromScRgb (transparency, mcolor.r, mcolor.g, mcolor.b))) ; //colorPlug =depNode.findPlug ("ambientColor") ; //mcolor.r =colorPlug.child (0).asFloat () ; //mcolor.g =colorPlug.child (1).asFloat () ; //mcolor.b =colorPlug.child (2).asFloat () ; //diffuse.AmbientColor =Color.FromScRgb (transparency, mcolor.r, mcolor.g, mcolor.b) ; //matGroup.Children.Add (diffuse) ; //colorPlug =depNode.findPlug ("specularColor") ; //mcolor.r =colorPlug.child (0).asFloat () ; //mcolor.g =colorPlug.child (1).asFloat () ; //mcolor.b =colorPlug.child (2).asFloat () ; //MPlug powerPlug =depNode.findPlug ("cosinePower") ; //SpecularMaterial specular =new SpecularMaterial (new SolidColorBrush (Color.FromScRgb (1.0f, mcolor.r, mcolor.g, mcolor.b)), powerPlug.asDouble ()) ; //matGroup.Children.Add (specular) ; //EmissiveMaterial emissive =new EmissiveMaterial () ; //matGroup.Children.Add (emissive) ; try { MFnLambertShader lambert =new MFnLambertShader (connections [u].node) ; SolidColorBrush brush =new SolidColorBrush (Color.FromScRgb (1.0f - lambert.transparency.r, lambert.color.r, lambert.color.g, lambert.color.b)) ; brush.Opacity =1.0f - lambert.transparency.r ; DiffuseMaterial diffuse =new DiffuseMaterial (brush) ; diffuse.AmbientColor =Color.FromScRgb (1.0f - lambert.ambientColor.a, lambert.ambientColor.r, lambert.ambientColor.g, lambert.ambientColor.b) ; // no more attributes matGroup.Children.Add (diffuse) ; // No specular color EmissiveMaterial emissive =new EmissiveMaterial (new SolidColorBrush (Color.FromScRgb (1.0f - lambert.incandescence.a, lambert.incandescence.r, lambert.incandescence.g, lambert.incandescence.b))) ; // no more attributes matGroup.Children.Add (emissive) ; } catch { } //try { // MFnReflectShader reflect =new MFnReflectShader (connections [u].node) ; // SpecularMaterial specular =new SpecularMaterial (new SolidColorBrush (Color.FromScRgb (1.0f - reflect.specularColor.a, reflect.specularColor.r, reflect.specularColor.g, reflect.specularColor.b)), reflect.cosPower) ; // // no more attributes // matGroup.Children.Add (specular) ; //} catch { //} try { MFnPhongShader phong =new MFnPhongShader (connections [u].node) ; //See Lambert //SolidColorBrush brush =new SolidColorBrush (Color.FromScRgb (1.0f - phong.transparency.r, phong.color.r, phong.color.g, phong.color.b)) ; //brush.Opacity =1.0f - phong.transparency.r ; //DiffuseMaterial diffuse =new DiffuseMaterial (brush) ; //diffuse.AmbientColor =Color.FromScRgb (1.0f - phong.ambientColor.a, phong.ambientColor.r, phong.ambientColor.g, phong.ambientColor.b) ; //// no more attributes //matGroup.Children.Add (diffuse) ; SpecularMaterial specular =new SpecularMaterial (new SolidColorBrush (Color.FromScRgb (1.0f - phong.specularColor.a, phong.specularColor.r, phong.specularColor.g, phong.specularColor.b)), phong.cosPower) ; // no more attributes matGroup.Children.Add (specular) ; //See Lambert //EmissiveMaterial emissive =new EmissiveMaterial (new SolidColorBrush (Color.FromScRgb (1.0f - phong.incandescence.a, phong.incandescence.r, phong.incandescence.g, phong.incandescence.b))) ; //// no more attributes //matGroup.Children.Add (emissive) ; } catch { } // todo //try { // MFnBlinnShader phong =new MFnBlinnShader (connections [u].node) ; // //See Lambert // //SolidColorBrush brush =new SolidColorBrush (Color.FromScRgb (1.0f - phong.transparency.r, phong.color.r, phong.color.g, phong.color.b)) ; // //brush.Opacity =1.0f - phong.transparency.r ; // //DiffuseMaterial diffuse =new DiffuseMaterial (brush) ; // //diffuse.AmbientColor = Color.FromScRgb (1.0f - phong.ambientColor.a, phong.ambientColor.r, phong.ambientColor.g, phong.ambientColor.b) ; // //// no more attributes // //matGroup.Children.Add (diffuse) ; // //See Lambert // //EmissiveMaterial emissive =new EmissiveMaterial (new SolidColorBrush (Color.FromScRgb (1.0f - phong.incandescence.a, phong.incandescence.r, phong.incandescence.g, phong.incandescence.b))) ; // //// no more attributes // //matGroup.Children.Add (emissive) ; //} catch { //} } } // Default to Blue if ( matGroup.Children.Count == 0 ) matGroup.Children.Add (new DiffuseMaterial (new SolidColorBrush (Color.FromRgb (0, 0, 255)))) ; return (matGroup) ; }
protected AssociationsSerializer fSerialize; // Serialization format public metadataBase() : base() { fMode = CommandMode.kCreate; fMeshes = new MObjectArray(); }
public Material MakeMaterial(MFnMesh fnMesh) { MaterialGroup matGroup = new MaterialGroup(); MObjectArray shaders = new MObjectArray(); MIntArray indices = new MIntArray(); fnMesh.getConnectedShaders(0, shaders, indices); for (int i = 0; i < shaders.length; i++) { MFnDependencyNode shaderGroup = new MFnDependencyNode(shaders [i]); MPlug shaderPlug = shaderGroup.findPlug("surfaceShader"); MPlugArray connections = new MPlugArray(); shaderPlug.connectedTo(connections, true, false); for (int u = 0; u < connections.length; u++) { MFnDependencyNode depNode = new MFnDependencyNode(connections [u].node); //MPlug colorPlug =depNode.findPlug ("color") ; //MColor mcolor =new MColor () ; ///*MPlugArray cc =new MPlugArray () ; //colorPlug.connectedTo (cc, true , false) ; //if ( cc.length > 0 ) { // // Plug is driven by an input connection. // for ( int v =0 ; v < cc.length ; v++ ) { // MPlug color2Plug =cc [v] ; // Console.WriteLine (color2Plug.numChildren) ; // color2Plug.child (0).getValue (mcolor.r) ; // color2Plug.child (1).getValue (mcolor.g) ; // color2Plug.child (2).getValue (mcolor.b) ; // //color2Plug.child (3).getValue (mcolor.a) ; // } //} else {*/ // mcolor.r =colorPlug.child (0).asFloat () ; // mcolor.g =colorPlug.child (1).asFloat () ; // mcolor.b =colorPlug.child (2).asFloat () ; // //colorPlug.child (3).getValue (mcolor.a) ; ////} //MPlug trPlug =depNode.findPlug ("transparency") ; //float transparency =1.0f - trPlug.child (0).asFloat () ; ////return new DiffuseMaterial (new SolidColorBrush (Color.FromScRgb (transparency, mcolor.r, mcolor.g, mcolor.b))) ; //DiffuseMaterial diffuse =new DiffuseMaterial (new SolidColorBrush (Color.FromScRgb (transparency, mcolor.r, mcolor.g, mcolor.b))) ; //colorPlug =depNode.findPlug ("ambientColor") ; //mcolor.r =colorPlug.child (0).asFloat () ; //mcolor.g =colorPlug.child (1).asFloat () ; //mcolor.b =colorPlug.child (2).asFloat () ; //diffuse.AmbientColor =Color.FromScRgb (transparency, mcolor.r, mcolor.g, mcolor.b) ; //matGroup.Children.Add (diffuse) ; //colorPlug =depNode.findPlug ("specularColor") ; //mcolor.r =colorPlug.child (0).asFloat () ; //mcolor.g =colorPlug.child (1).asFloat () ; //mcolor.b =colorPlug.child (2).asFloat () ; //MPlug powerPlug =depNode.findPlug ("cosinePower") ; //SpecularMaterial specular =new SpecularMaterial (new SolidColorBrush (Color.FromScRgb (1.0f, mcolor.r, mcolor.g, mcolor.b)), powerPlug.asDouble ()) ; //matGroup.Children.Add (specular) ; //EmissiveMaterial emissive =new EmissiveMaterial () ; //matGroup.Children.Add (emissive) ; try { MFnLambertShader lambert = new MFnLambertShader(connections [u].node); SolidColorBrush brush = new SolidColorBrush(Color.FromScRgb(1.0f - lambert.transparency.r, lambert.color.r, lambert.color.g, lambert.color.b)); brush.Opacity = 1.0f - lambert.transparency.r; DiffuseMaterial diffuse = new DiffuseMaterial(brush); diffuse.AmbientColor = Color.FromScRgb(1.0f - lambert.ambientColor.a, lambert.ambientColor.r, lambert.ambientColor.g, lambert.ambientColor.b); // no more attributes matGroup.Children.Add(diffuse); // No specular color EmissiveMaterial emissive = new EmissiveMaterial(new SolidColorBrush(Color.FromScRgb(1.0f - lambert.incandescence.a, lambert.incandescence.r, lambert.incandescence.g, lambert.incandescence.b))); // no more attributes matGroup.Children.Add(emissive); } catch { } //try { // MFnReflectShader reflect =new MFnReflectShader (connections [u].node) ; // SpecularMaterial specular =new SpecularMaterial (new SolidColorBrush (Color.FromScRgb (1.0f - reflect.specularColor.a, reflect.specularColor.r, reflect.specularColor.g, reflect.specularColor.b)), reflect.cosPower) ; // // no more attributes // matGroup.Children.Add (specular) ; //} catch { //} try { MFnPhongShader phong = new MFnPhongShader(connections [u].node); //See Lambert //SolidColorBrush brush =new SolidColorBrush (Color.FromScRgb (1.0f - phong.transparency.r, phong.color.r, phong.color.g, phong.color.b)) ; //brush.Opacity =1.0f - phong.transparency.r ; //DiffuseMaterial diffuse =new DiffuseMaterial (brush) ; //diffuse.AmbientColor =Color.FromScRgb (1.0f - phong.ambientColor.a, phong.ambientColor.r, phong.ambientColor.g, phong.ambientColor.b) ; //// no more attributes //matGroup.Children.Add (diffuse) ; SpecularMaterial specular = new SpecularMaterial(new SolidColorBrush(Color.FromScRgb(1.0f - phong.specularColor.a, phong.specularColor.r, phong.specularColor.g, phong.specularColor.b)), phong.cosPower); // no more attributes matGroup.Children.Add(specular); //See Lambert //EmissiveMaterial emissive =new EmissiveMaterial (new SolidColorBrush (Color.FromScRgb (1.0f - phong.incandescence.a, phong.incandescence.r, phong.incandescence.g, phong.incandescence.b))) ; //// no more attributes //matGroup.Children.Add (emissive) ; } catch { } // todo //try { // MFnBlinnShader phong =new MFnBlinnShader (connections [u].node) ; // //See Lambert // //SolidColorBrush brush =new SolidColorBrush (Color.FromScRgb (1.0f - phong.transparency.r, phong.color.r, phong.color.g, phong.color.b)) ; // //brush.Opacity =1.0f - phong.transparency.r ; // //DiffuseMaterial diffuse =new DiffuseMaterial (brush) ; // //diffuse.AmbientColor = Color.FromScRgb (1.0f - phong.ambientColor.a, phong.ambientColor.r, phong.ambientColor.g, phong.ambientColor.b) ; // //// no more attributes // //matGroup.Children.Add (diffuse) ; // //See Lambert // //EmissiveMaterial emissive =new EmissiveMaterial (new SolidColorBrush (Color.FromScRgb (1.0f - phong.incandescence.a, phong.incandescence.r, phong.incandescence.g, phong.incandescence.b))) ; // //// no more attributes // //matGroup.Children.Add (emissive) ; //} catch { //} } } // Default to Blue if (matGroup.Children.Count == 0) { matGroup.Children.Add(new DiffuseMaterial(new SolidColorBrush(Color.FromRgb(0, 0, 255)))); } return(matGroup); }
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 static List <Surface> meshToNurbs(MFnMesh mayaMesh) { MFnSubd subDmesh = new MFnSubd(); subDmesh.isIntermediateObject = true; MPointArray mayaVerts = new MPointArray(); mayaMesh.getPoints(mayaVerts, MSpace.Space.kWorld); MIntArray polyVertct = new MIntArray(); MIntArray ids = new MIntArray(); MIntArray idList = new MIntArray(); for (int i = 0; i < mayaMesh.numPolygons; i++) { mayaMesh.getPolygonVertices(i, ids); foreach (var id in ids) { idList.Add(id); } polyVertct.Add(ids.Count); } subDmesh.createBaseMesh(false, mayaMesh.numVertices, mayaMesh.numPolygons, mayaVerts, polyVertct, idList); try { MUintArray creaseEdgId = new MUintArray(); MDoubleArray creaseEdgeVal = new MDoubleArray(); mayaMesh.getCreaseEdges(creaseEdgId, creaseEdgeVal); foreach (var edgId in creaseEdgId) { subDmesh.edgeSetCrease(edgId, true); } } catch {} try { MUintArray creaseVertId = new MUintArray(); MDoubleArray creaseVertVal = new MDoubleArray(); mayaMesh.getCreaseVertices(creaseVertId, creaseVertVal); foreach (var vertId in creaseVertId) { subDmesh.vertexSetCrease(vertId, true); } } catch { } subDmesh.updateAllEditsAndCreases(); MObjectArray nurbsSurfs = new MObjectArray(); subDmesh.convertToNurbs(nurbsSurfs); List <MFnNurbsSurface> mfnSurfaceList = new List <MFnNurbsSurface>(nurbsSurfs.Count); foreach (var surf in nurbsSurfs) { mfnSurfaceList.Add(new MFnNurbsSurface(surf)); } List <Surface> dynSurfaceList = new List <Surface>(mfnSurfaceList.Count); foreach (var mfnNS in mfnSurfaceList) { dynSurfaceList.Add(DMSurface.mNurbsSurfaceToDynamoSurface(mfnNS, MSpace.Space.kObject)); } MGlobal.deleteNode(subDmesh.model); return(dynSurfaceList); }
/// <summary> /// /// </summary> /// <param name="mDagPath">DAG path to the transform above mesh</param> /// <param name="babylonScene"></param> /// <returns></returns> private BabylonNode ExportMesh(MDagPath mDagPath, BabylonScene babylonScene) { RaiseMessage(mDagPath.partialPathName, 1); // Transform above mesh MFnTransform mFnTransform = new MFnTransform(mDagPath); // Mesh direct child of the transform MFnMesh mFnMesh = null; for (uint i = 0; i < mFnTransform.childCount; i++) { MObject childObject = mFnTransform.child(i); if (childObject.apiType == MFn.Type.kMesh) { var _mFnMesh = new MFnMesh(childObject); if (!_mFnMesh.isIntermediateObject) { mFnMesh = _mFnMesh; } } } if (mFnMesh == null) { RaiseError("No mesh found has child of " + mDagPath.fullPathName); return(null); } RaiseMessage("mFnMesh.fullPathName=" + mFnMesh.fullPathName, 2); // --- prints --- #region prints Action <MFnDagNode> printMFnDagNode = (MFnDagNode mFnDagNode) => { RaiseVerbose("BabylonExporter.Mesh | mFnDagNode.name=" + mFnDagNode.name, 3); RaiseVerbose("BabylonExporter.Mesh | mFnDagNode.absoluteName=" + mFnDagNode.absoluteName, 3); RaiseVerbose("BabylonExporter.Mesh | mFnDagNode.fullPathName=" + mFnDagNode.fullPathName, 3); RaiseVerbose("BabylonExporter.Mesh | mFnDagNode.partialPathName=" + mFnDagNode.partialPathName, 3); RaiseVerbose("BabylonExporter.Mesh | mFnDagNode.activeColor=" + mFnDagNode.activeColor.toString(), 3); RaiseVerbose("BabylonExporter.Mesh | mFnDagNode.attributeCount=" + mFnDagNode.attributeCount, 3); RaiseVerbose("BabylonExporter.Mesh | mFnDagNode.childCount=" + mFnDagNode.childCount, 3); RaiseVerbose("BabylonExporter.Mesh | mFnDagNode.dormantColor=" + mFnDagNode.dormantColor, 3); RaiseVerbose("BabylonExporter.Mesh | mFnDagNode.hasUniqueName=" + mFnDagNode.hasUniqueName, 3); RaiseVerbose("BabylonExporter.Mesh | mFnDagNode.inUnderWorld=" + mFnDagNode.inUnderWorld, 3); RaiseVerbose("BabylonExporter.Mesh | mFnDagNode.isDefaultNode=" + mFnDagNode.isDefaultNode, 3); RaiseVerbose("BabylonExporter.Mesh | mFnDagNode.isInstanceable=" + mFnDagNode.isInstanceable, 3); RaiseVerbose("BabylonExporter.Mesh | mFnDagNode.isInstanced(true)=" + mFnDagNode.isInstanced(true), 3); RaiseVerbose("BabylonExporter.Mesh | mFnDagNode.isInstanced(false)=" + mFnDagNode.isInstanced(false), 3); RaiseVerbose("BabylonExporter.Mesh | mFnDagNode.isInstanced()=" + mFnDagNode.isInstanced(), 3); RaiseVerbose("BabylonExporter.Mesh | mFnDagNode.instanceCount(true)=" + mFnDagNode.instanceCount(true), 3); RaiseVerbose("BabylonExporter.Mesh | mFnDagNode.instanceCount(false)=" + mFnDagNode.instanceCount(false), 3); RaiseVerbose("BabylonExporter.Mesh | mFnDagNode.isIntermediateObject=" + mFnDagNode.isIntermediateObject, 3); RaiseVerbose("BabylonExporter.Mesh | mFnDagNode.isShared=" + mFnDagNode.isShared, 3); RaiseVerbose("BabylonExporter.Mesh | mFnDagNode.objectColor=" + mFnDagNode.objectColor, 3); RaiseVerbose("BabylonExporter.Mesh | mFnDagNode.parentCount=" + mFnDagNode.parentCount, 3); RaiseVerbose("BabylonExporter.Mesh | mFnDagNode.parentNamespace=" + mFnDagNode.parentNamespace, 3); RaiseVerbose("BabylonExporter.Mesh | mFnDagNode.uuid().asString()=" + mFnDagNode.uuid().asString(), 3); RaiseVerbose("BabylonExporter.Mesh | mFnDagNode.dagRoot().apiType=" + mFnDagNode.dagRoot().apiType, 3); RaiseVerbose("BabylonExporter.Mesh | mFnDagNode.model.equalEqual(mFnDagNode.objectProperty)=" + mFnDagNode.model.equalEqual(mFnDagNode.objectProperty), 3); RaiseVerbose("BabylonExporter.Mesh | mFnDagNode.transformationMatrix.toString()=" + mFnDagNode.transformationMatrix.toString(), 3); }; Action <MFnMesh> printMFnMesh = (MFnMesh _mFnMesh) => { printMFnDagNode(mFnMesh); RaiseVerbose("BabylonExporter.Mesh | _mFnMesh.numVertices=" + _mFnMesh.numVertices, 3); RaiseVerbose("BabylonExporter.Mesh | _mFnMesh.numEdges=" + _mFnMesh.numEdges, 3); RaiseVerbose("BabylonExporter.Mesh | _mFnMesh.numPolygons=" + _mFnMesh.numPolygons, 3); RaiseVerbose("BabylonExporter.Mesh | _mFnMesh.numFaceVertices=" + _mFnMesh.numFaceVertices, 3); RaiseVerbose("BabylonExporter.Mesh | _mFnMesh.numNormals=" + _mFnMesh.numNormals, 3); RaiseVerbose("BabylonExporter.Mesh | _mFnMesh.numUVSets=" + _mFnMesh.numUVSets, 3); RaiseVerbose("BabylonExporter.Mesh | _mFnMesh.numUVsProperty=" + _mFnMesh.numUVsProperty, 3); RaiseVerbose("BabylonExporter.Mesh | _mFnMesh.displayColors=" + _mFnMesh.displayColors, 3); RaiseVerbose("BabylonExporter.Mesh | _mFnMesh.numColorSets=" + _mFnMesh.numColorSets, 3); RaiseVerbose("BabylonExporter.Mesh | _mFnMesh.numColorsProperty=" + _mFnMesh.numColorsProperty, 3); RaiseVerbose("BabylonExporter.Mesh | _mFnMesh.currentUVSetName()=" + _mFnMesh.currentUVSetName(), 3); var _uvSetNames = new MStringArray(); mFnMesh.getUVSetNames(_uvSetNames); foreach (var uvSetName in _uvSetNames) { RaiseVerbose("BabylonExporter.Mesh | uvSetName=" + uvSetName, 3); RaiseVerbose("BabylonExporter.Mesh | mFnMesh.numUVs(uvSetName)=" + mFnMesh.numUVs(uvSetName), 4); MFloatArray us = new MFloatArray(); MFloatArray vs = new MFloatArray(); mFnMesh.getUVs(us, vs, uvSetName); RaiseVerbose("BabylonExporter.Mesh | us.Count=" + us.Count, 4); } }; Action <MFnTransform> printMFnTransform = (MFnTransform _mFnMesh) => { printMFnDagNode(mFnMesh); }; RaiseVerbose("BabylonExporter.Mesh | mFnMesh data", 2); printMFnMesh(mFnMesh); RaiseVerbose("BabylonExporter.Mesh | mFnTransform data", 2); printMFnTransform(mFnTransform); Print(mFnTransform, 2, "Print ExportMesh mFnTransform"); Print(mFnMesh, 2, "Print ExportMesh mFnMesh"); //// Geometry //MIntArray triangleCounts = new MIntArray(); //MIntArray trianglesVertices = new MIntArray(); //mFnMesh.getTriangles(triangleCounts, trianglesVertices); //RaiseVerbose("BabylonExporter.Mesh | triangleCounts.ToArray()=" + triangleCounts.ToArray().toString(), 3); //RaiseVerbose("BabylonExporter.Mesh | trianglesVertices.ToArray()=" + trianglesVertices.ToArray().toString(), 3); //int[] polygonsVertexCount = new int[mFnMesh.numPolygons]; //for (int polygonId = 0; polygonId < mFnMesh.numPolygons; polygonId++) //{ // polygonsVertexCount[polygonId] = mFnMesh.polygonVertexCount(polygonId); //} //RaiseVerbose("BabylonExporter.Mesh | polygonsVertexCount=" + polygonsVertexCount.toString(), 3); ////MFloatPointArray points = new MFloatPointArray(); ////mFnMesh.getPoints(points); ////RaiseVerbose("BabylonExporter.Mesh | points.ToArray()=" + points.ToArray().Select(mFloatPoint => mFloatPoint.toString()), 3); ////MFloatVectorArray normals = new MFloatVectorArray(); ////mFnMesh.getNormals(normals); ////RaiseVerbose("BabylonExporter.Mesh | normals.ToArray()=" + normals.ToArray().Select(mFloatPoint => mFloatPoint.toString()), 3); //for (int polygonId = 0; polygonId < mFnMesh.numPolygons; polygonId++) //{ // MIntArray verticesId = new MIntArray(); // RaiseVerbose("BabylonExporter.Mesh | polygonId=" + polygonId, 3); // int nbTriangles = triangleCounts[polygonId]; // RaiseVerbose("BabylonExporter.Mesh | nbTriangles=" + nbTriangles, 3); // for (int triangleIndex = 0; triangleIndex < triangleCounts[polygonId]; triangleIndex++) // { // RaiseVerbose("BabylonExporter.Mesh | triangleIndex=" + triangleIndex, 3); // int[] triangleVertices = new int[3]; // mFnMesh.getPolygonTriangleVertices(polygonId, triangleIndex, triangleVertices); // RaiseVerbose("BabylonExporter.Mesh | triangleVertices=" + triangleVertices.toString(), 3); // foreach (int vertexId in triangleVertices) // { // RaiseVerbose("BabylonExporter.Mesh | vertexId=" + vertexId, 3); // MPoint point = new MPoint(); // mFnMesh.getPoint(vertexId, point); // RaiseVerbose("BabylonExporter.Mesh | point=" + point.toString(), 3); // MVector normal = new MVector(); // mFnMesh.getFaceVertexNormal(polygonId, vertexId, normal); // RaiseVerbose("BabylonExporter.Mesh | normal=" + normal.toString(), 3); // } // } //} #endregion if (IsMeshExportable(mFnMesh, mDagPath) == false) { return(null); } var babylonMesh = new BabylonMesh { name = mFnTransform.name, id = mFnTransform.uuid().asString() }; // Position / rotation / scaling / hierarchy ExportNode(babylonMesh, mFnTransform, babylonScene); // Misc. // TODO - Retreive from Maya // TODO - What is the difference between isVisible and visibility? // TODO - Fix fatal error: Attempting to save in C:/Users/Fabrice/AppData/Local/Temp/Fabrice.20171205.1613.ma //babylonMesh.isVisible = mDagPath.isVisible; //babylonMesh.visibility = meshNode.MaxNode.GetVisibility(0, Tools.Forever); //babylonMesh.receiveShadows = meshNode.MaxNode.RcvShadows == 1; //babylonMesh.applyFog = meshNode.MaxNode.ApplyAtmospherics == 1; if (mFnMesh.numPolygons < 1) { RaiseError($"Mesh {babylonMesh.name} has no face", 2); } if (mFnMesh.numVertices < 3) { RaiseError($"Mesh {babylonMesh.name} has not enough vertices", 2); } if (mFnMesh.numVertices >= 65536) { RaiseWarning($"Mesh {babylonMesh.name} has more than 65536 vertices which means that it will require specific WebGL extension to be rendered. This may impact portability of your scene on low end devices.", 2); } // Material MObjectArray shaders = new MObjectArray(); mFnMesh.getConnectedShaders(0, shaders, new MIntArray()); if (shaders.Count > 0) { List <MFnDependencyNode> materials = new List <MFnDependencyNode>(); foreach (MObject shader in shaders) { // Retreive material MFnDependencyNode shadingEngine = new MFnDependencyNode(shader); MPlug mPlugSurfaceShader = shadingEngine.findPlug("surfaceShader"); MObject materialObject = mPlugSurfaceShader.source.node; MFnDependencyNode material = new MFnDependencyNode(materialObject); materials.Add(material); } if (shaders.Count == 1) { MFnDependencyNode material = materials[0]; // Material is referenced by id babylonMesh.materialId = material.uuid().asString(); // Register material for export if not already done if (!referencedMaterials.Contains(material, new MFnDependencyNodeEqualityComparer())) { referencedMaterials.Add(material); } } else { // Create a new id for the group of sub materials string uuidMultiMaterial = GetMultimaterialUUID(materials); // Multi material is referenced by id babylonMesh.materialId = uuidMultiMaterial; // Register multi material for export if not already done if (!multiMaterials.ContainsKey(uuidMultiMaterial)) { multiMaterials.Add(uuidMultiMaterial, materials); } } } var vertices = new List <GlobalVertex>(); var indices = new List <int>(); var uvSetNames = new MStringArray(); mFnMesh.getUVSetNames(uvSetNames); bool[] isUVExportSuccess = new bool[Math.Min(uvSetNames.Count, 2)]; for (int indexUVSet = 0; indexUVSet < isUVExportSuccess.Length; indexUVSet++) { isUVExportSuccess[indexUVSet] = true; } // TODO - color, alpha //var hasColor = unskinnedMesh.NumberOfColorVerts > 0; //var hasAlpha = unskinnedMesh.GetNumberOfMapVerts(-2) > 0; // TODO - Add custom properties var optimizeVertices = false; // meshNode.MaxNode.GetBoolProperty("babylonjs_optimizevertices"); // Compute normals var subMeshes = new List <BabylonSubMesh>(); ExtractGeometry(mFnMesh, vertices, indices, subMeshes, uvSetNames, ref isUVExportSuccess, optimizeVertices); if (vertices.Count >= 65536) { RaiseWarning($"Mesh {babylonMesh.name} has {vertices.Count} vertices. This may prevent your scene to work on low end devices where 32 bits indice are not supported", 2); if (!optimizeVertices) { RaiseError("You can try to optimize your object using [Try to optimize vertices] option", 2); } } for (int indexUVSet = 0; indexUVSet < isUVExportSuccess.Length; indexUVSet++) { string uvSetName = uvSetNames[indexUVSet]; // If at least one vertex is mapped to an UV coordinate but some have failed to be exported if (isUVExportSuccess[indexUVSet] == false && mFnMesh.numUVs(uvSetName) > 0) { RaiseWarning($"Failed to export UV set named {uvSetName}. Ensure all vertices are mapped to a UV coordinate.", 2); } } RaiseMessage($"{vertices.Count} vertices, {indices.Count / 3} faces", 2); // Buffers babylonMesh.positions = vertices.SelectMany(v => v.Position).ToArray(); babylonMesh.normals = vertices.SelectMany(v => v.Normal).ToArray(); // TODO - Export colors ? //babylonMesh.colors = vertices.SelectMany(v => v.Color).ToArray(); if (uvSetNames.Count > 0 && isUVExportSuccess[0]) { babylonMesh.uvs = vertices.SelectMany(v => v.UV).ToArray(); } if (uvSetNames.Count > 1 && isUVExportSuccess[1]) { babylonMesh.uvs2 = vertices.SelectMany(v => v.UV2).ToArray(); } babylonMesh.subMeshes = subMeshes.ToArray(); // Buffers - Indices babylonMesh.indices = indices.ToArray(); babylonScene.MeshesList.Add(babylonMesh); RaiseMessage("BabylonExporter.Mesh | done", 2); return(babylonMesh); }
public override void doIt(MArgList args) { // parse the command arguments // parseArgs(args); uint count = 0; // if the character flag was used, create the clip on the specified // character, otherwise, create a character // MFnCharacter fnCharacter = new MFnCharacter(); if (fCharacter.isNull) { MSelectionList activeList = new MSelectionList(); MGlobal.getActiveSelectionList(activeList); if (0 == activeList.length) { throw new ApplicationException("Empty Active Selection List."); } // create a character using the selection list // fCharacter = fnCharacter.create(activeList, MFnSet.Restriction.kNone); } else { fnCharacter.setObject(fCharacter); } // Get the array of members of the character. We will create a clip // for them. // MPlugArray plugs = new MPlugArray(); fnCharacter.getMemberPlugs(plugs); // Now create a animCurves to use as a clip for the character. // The curves will be set up between frames 0 and 10; // MTime start = new MTime(0.0); MTime duration = new MTime(10.0); MObjectArray clipCurves = new MObjectArray(); for (count = 0; count < plugs.length; ++count) { // Now create a bunch of animCurves to use as a clip for the // character // MFnAnimCurve fnCurve = new MFnAnimCurve(); MObject curve = fnCurve.create(MFnAnimCurve.AnimCurveType.kAnimCurveTL); // plugType); fnCurve.addKeyframe(start, 5.0); fnCurve.addKeyframe(duration, 15.0); clipCurves.append(curve); } // Create a source clip node and add the animation to it // MFnClip fnClipCreate = new MFnClip(); MObject sourceClip = fnClipCreate.createSourceClip(start, duration, fMod); fnCharacter.attachSourceToCharacter(sourceClip, fMod); for (count = 0; count < plugs.length; ++count) { MPlug animPlug = plugs[(int)count]; fnCharacter.addCurveToClip(clipCurves[(int)count], sourceClip, animPlug, fMod); } // instance the clip // MTime schedStart = new MTime(15.0); MObject instancedClip = fnClipCreate.createInstancedClip(sourceClip, schedStart, fMod); fnCharacter.attachInstanceToCharacter(instancedClip, fMod); // instance the clip a second time, at time 30 // schedStart.value = 30.0; MObject instancedClip2 = fnClipCreate.createInstancedClip(sourceClip, schedStart, fMod); fnCharacter.attachInstanceToCharacter(instancedClip2, fMod); return; }
// // Description: // Overloaded function from MPxDragAndDropBehavior // this method will handle the connection between the slopeShaderNodeCSharp and the shader it is // assigned to as well as any meshes that it is assigned to. // public override void connectNodeToNode(MObject sourceNode, MObject destinationNode, bool force) { MFnDependencyNode src = new MFnDependencyNode(sourceNode); //if we are dragging from a lambert //we want to check what we are dragging //onto. if(sourceNode.hasFn(MFn.Type.kLambert)) { //MObject shaderNode; MPlugArray connections = new MPlugArray(); MObjectArray shaderNodes = new MObjectArray(); shaderNodes.clear(); //if the source node was a lambert //than we will check the downstream connections to see //if a slope shader is assigned to it. // src.getConnections(connections); int i; for(i = 0; i < connections.length; i++) { //check the incoming connections to this plug // MPlugArray connectedPlugs = new MPlugArray(); connections[i].connectedTo(connectedPlugs, true, false); for(uint j = 0; j < connectedPlugs.length; j++) { //if the incoming node is a slope shader than //append the node to the shaderNodes array // MObject currentnode = connectedPlugs[i].node; if (new MFnDependencyNode(currentnode).typeName == "slopeShaderNodeCSharp") { shaderNodes.append(currentnode); } } } //if we found a shading node //than check the destination node //type to see if it is a mesh // if(shaderNodes.length > 0) { MFnDependencyNode dest = new MFnDependencyNode(destinationNode); if(destinationNode.hasFn(MFn.Type.kMesh)) { //if the node is a mesh than for each slopeShaderNodeCSharp //connect the worldMesh attribute to the dirtyShaderPlug //attribute to force an evaluation of the node when the mesh //changes // for(i = 0; i < shaderNodes.length; i++) { MPlug srcPlug = dest.findPlug("worldMesh"); MPlug destPlug = new MFnDependencyNode(shaderNodes[i]).findPlug("dirtyShaderPlug"); if(!srcPlug.isNull && !destPlug.isNull) { string cmd = "connectAttr -na "; cmd += srcPlug.name + " "; cmd += destPlug.name; try { // in slopeShaderBehavior.cpp, this may excute failed but continue on the following code, so we catch it. MGlobal.executeCommand(cmd); } catch (System.Exception) { MGlobal.displayError("ExcuteCommand (" + cmd + ") failed."); } } } //get the shading engine so we can assign the shader //to the mesh after doing the connection // MObject shadingEngine = findShadingEngine(sourceNode); //if there is a valid shading engine than make //the connection // if(!shadingEngine.isNull) { string cmd = "sets -edit -forceElement "; cmd += new MFnDependencyNode(shadingEngine).name + " "; cmd += new MFnDagNode(destinationNode).partialPathName; MGlobal.executeCommand(cmd); } } } } else if (src.typeName == "slopeShaderNodeCSharp") //if we are dragging from a slope shader //than we want to see what we are dragging onto // { if(destinationNode.hasFn(MFn.Type.kMesh)) { //if the user is dragging onto a mesh //than make the connection from the worldMesh //to the dirtyShader plug on the slopeShaderNodeCSharp // MFnDependencyNode dest = new MFnDependencyNode(destinationNode); MPlug srcPlug = dest.findPlug("worldMesh"); MPlug destPlug = src.findPlug("dirtyShaderPlug"); if(!srcPlug.isNull && !destPlug.isNull) { string cmd = "connectAttr -na "; cmd += srcPlug.name + " "; cmd += destPlug.name; MGlobal.executeCommand(cmd); } } } return; }
protected override void getOutputAttributes(MObjectArray attributeArray) { attributeArray.clear(); attributeArray.append(GeometrySurfaceConstraint.constraintGeometry); }
public apiSimpleShapeIterator(object userGeometry, MObjectArray components) : base(userGeometry, components) { mGeometry = userGeometry as MVectorArray; reset(); }
public override void doIt(MArgList args) { // parse the command arguments // parseArgs(args); uint count = 0; // if the character flag was used, create the clip on the specified // character, otherwise, create a character // MFnCharacter fnCharacter = new MFnCharacter(); if (fCharacter.isNull) { MSelectionList activeList = new MSelectionList(); MGlobal.getActiveSelectionList(activeList); if (0 == activeList.length) { throw new ApplicationException("Empty Active Selection List."); } // create a character using the selection list // fCharacter = fnCharacter.create(activeList, MFnSet.Restriction.kNone); } else fnCharacter.setObject(fCharacter); // Get the array of members of the character. We will create a clip // for them. // MPlugArray plugs = new MPlugArray(); fnCharacter.getMemberPlugs(plugs); // Now create a animCurves to use as a clip for the character. // The curves will be set up between frames 0 and 10; // MTime start = new MTime(0.0); MTime duration = new MTime(10.0); MObjectArray clipCurves = new MObjectArray(); for (count = 0; count < plugs.length; ++count) { // Now create a bunch of animCurves to use as a clip for the // character // MFnAnimCurve fnCurve = new MFnAnimCurve(); MObject curve = fnCurve.create(MFnAnimCurve.AnimCurveType.kAnimCurveTL); // plugType); fnCurve.addKeyframe(start, 5.0); fnCurve.addKeyframe(duration, 15.0); clipCurves.append(curve); } // Create a source clip node and add the animation to it // MFnClip fnClipCreate = new MFnClip(); MObject sourceClip = fnClipCreate.createSourceClip(start, duration, fMod); fnCharacter.attachSourceToCharacter(sourceClip, fMod); for (count = 0; count < plugs.length; ++count) { MPlug animPlug = plugs[(int)count]; fnCharacter.addCurveToClip(clipCurves[(int)count], sourceClip, animPlug, fMod); } // instance the clip // MTime schedStart = new MTime(15.0); MObject instancedClip = fnClipCreate.createInstancedClip(sourceClip, schedStart, fMod); fnCharacter.attachInstanceToCharacter(instancedClip, fMod); // instance the clip a second time, at time 30 // schedStart.value = 30.0; MObject instancedClip2 = fnClipCreate.createInstancedClip(sourceClip, schedStart, fMod); fnCharacter.attachInstanceToCharacter(instancedClip2, fMod); return; }
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"); }
// // Description // // Transforms the given components. This method is used by // the move, rotate, and scale tools in component mode. // The bounding box has to be updated here, so do the normals and // any other attributes that depend on vertex positions. // // Arguments // mat - matrix to transform the components by // componentList - list of components to be transformed, // or an empty list to indicate the whole surface // cachingMode - how to use the supplied pointCache // pointCache - if non-null, save or restore points from this list base // on the cachingMode // public override void transformUsing(MMatrix mat, MObjectArray componentList, MVertexCachingMode cachingMode, MPointArray pointCache) { apiMeshGeom geomPtr = meshGeom(); bool savePoints = (cachingMode == MVertexCachingMode.kSavePoints); int i = 0, j = 0; uint len = componentList.length; if (cachingMode == MVertexCachingMode.kRestorePoints) { // restore the points based on the data provided in the pointCache attribute // uint cacheLen = pointCache.length; if (len > 0) { // traverse the component list // for ( i = 0; i < len && j < cacheLen; i++ ) { MObject comp = componentList[i]; MFnSingleIndexedComponent fnComp = new MFnSingleIndexedComponent( comp ); int elemCount = fnComp.elementCount; for ( int idx=0; idx<elemCount && j < cacheLen; idx++, ++j ) { int elemIndex = fnComp.element( idx ); geomPtr.vertices[elemIndex] = pointCache[j]; } } } else { // if the component list is of zero-length, it indicates that we // should transform the entire surface // len = geomPtr.vertices.length; for ( int idx = 0; idx < len && j < cacheLen; ++idx, ++j ) { geomPtr.vertices[idx] = pointCache[j]; } } } else { // Transform the surface vertices with the matrix. // If savePoints is true, save the points to the pointCache. // if (len > 0) { // Traverse the componentList // for ( i=0; i<len; i++ ) { MObject comp = componentList[i]; MFnSingleIndexedComponent fnComp = new MFnSingleIndexedComponent( comp ); uint elemCount = (uint)fnComp.elementCount; if (savePoints && 0 == i) { pointCache.sizeIncrement = elemCount; } for ( int idx=0; idx<elemCount; idx++ ) { int elemIndex = fnComp.element( (int)idx ); if (savePoints) { pointCache.append(geomPtr.vertices[elemIndex]); } geomPtr.vertices[elemIndex].multiplyEqual( mat ); geomPtr.normals[idx] = geomPtr.normals[idx].transformAsNormal( mat ); } } } else { // If the component list is of zero-length, it indicates that we // should transform the entire surface // len = geomPtr.vertices.length; if (savePoints) { pointCache.sizeIncrement = len; } for ( int idx = 0; idx < len; ++idx ) { if (savePoints) { pointCache.append(geomPtr.vertices[idx]); } geomPtr.vertices[idx].multiplyEqual( mat ); geomPtr.normals[idx] = geomPtr.normals[idx].transformAsNormal( mat ); } } } // Retrieve the value of the cached surface attribute. // We will set the new geometry data into the cached surface attribute // // Access the datablock directly. This code has to be efficient // and so we bypass the compute mechanism completely. // NOTE: In general we should always go though compute for getting // and setting attributes. // MDataBlock datablock = _forceCache(); MDataHandle cachedHandle = datablock.outputValue( cachedSurface ); apiMeshData cached = cachedHandle.asPluginData as apiMeshData; MDataHandle dHandle = datablock.outputValue( mControlPoints ); // If there is history then calculate the tweaks necessary for // setting the final positions of the vertices. // if ( hasHistory() && (null != cached) ) { // Since the shape has history, we need to store the tweaks (deltas) // between the input shape and the tweaked shape in the control points // attribute. // buildControlPoints( datablock, (int)geomPtr.vertices.length ); MArrayDataHandle cpHandle = new MArrayDataHandle( dHandle ); // Loop through the component list and transform each vertex. // for ( i=0; i<len; i++ ) { MObject comp = componentList[i]; MFnSingleIndexedComponent fnComp = new MFnSingleIndexedComponent( comp ); int elemCount = fnComp.elementCount; for ( int idx=0; idx<elemCount; idx++ ) { int elemIndex = fnComp.element( idx ); cpHandle.jumpToElement( (uint)elemIndex ); MDataHandle pntHandle = cpHandle.outputValue(); double[] pnt = pntHandle.Double3; MPoint oldPnt = cached.fGeometry.vertices[elemIndex]; MPoint newPnt = geomPtr.vertices[elemIndex]; MVector offset = newPnt.minus( oldPnt ); pnt[0] += offset[0]; pnt[1] += offset[1]; pnt[2] += offset[2]; pntHandle.Double3 = pnt; } } } // Copy outputSurface to cachedSurface // if ( null == cached ) { MGlobal.displayInfo("NULL cachedSurface data found"); } else { cached.fGeometry = geomPtr; } MPlug pCPs = new MPlug( thisMObject(), mControlPoints ); pCPs.setValue(dHandle); // Moving vertices will likely change the bounding box. // computeBoundingBox( datablock ); // Tell Maya the bounding box for this object has changed // and thus "boundingBox()" needs to be called. // childChanged( MChildChanged.kBoundingBoxChanged ); }
/// <summary> /// /// </summary> /// <param name="mDagPath">DAG path to the transform above mesh</param> /// <param name="babylonScene"></param> /// <returns></returns> private BabylonNode ExportMesh(MDagPath mDagPath, BabylonScene babylonScene) { RaiseMessage(mDagPath.partialPathName, 1); // Transform above mesh mFnTransform = new MFnTransform(mDagPath); // Mesh direct child of the transform // TODO get the original one rather than the modified? MFnMesh mFnMesh = null; for (uint i = 0; i < mFnTransform.childCount; i++) { MObject childObject = mFnTransform.child(i); if (childObject.apiType == MFn.Type.kMesh) { var _mFnMesh = new MFnMesh(childObject); if (!_mFnMesh.isIntermediateObject) { mFnMesh = _mFnMesh; } } } if (mFnMesh == null) { RaiseError("No mesh found has child of " + mDagPath.fullPathName); return(null); } RaiseMessage("mFnMesh.fullPathName=" + mFnMesh.fullPathName, 2); // --- prints --- #region prints Action <MFnDagNode> printMFnDagNode = (MFnDagNode mFnDagNode) => { RaiseVerbose("BabylonExporter.Mesh | mFnDagNode.name=" + mFnDagNode.name, 3); RaiseVerbose("BabylonExporter.Mesh | mFnDagNode.absoluteName=" + mFnDagNode.absoluteName, 3); RaiseVerbose("BabylonExporter.Mesh | mFnDagNode.fullPathName=" + mFnDagNode.fullPathName, 3); RaiseVerbose("BabylonExporter.Mesh | mFnDagNode.partialPathName=" + mFnDagNode.partialPathName, 3); RaiseVerbose("BabylonExporter.Mesh | mFnDagNode.activeColor=" + mFnDagNode.activeColor.toString(), 3); RaiseVerbose("BabylonExporter.Mesh | mFnDagNode.attributeCount=" + mFnDagNode.attributeCount, 3); RaiseVerbose("BabylonExporter.Mesh | mFnDagNode.childCount=" + mFnDagNode.childCount, 3); RaiseVerbose("BabylonExporter.Mesh | mFnDagNode.dormantColor=" + mFnDagNode.dormantColor, 3); RaiseVerbose("BabylonExporter.Mesh | mFnDagNode.hasUniqueName=" + mFnDagNode.hasUniqueName, 3); RaiseVerbose("BabylonExporter.Mesh | mFnDagNode.inUnderWorld=" + mFnDagNode.inUnderWorld, 3); RaiseVerbose("BabylonExporter.Mesh | mFnDagNode.isDefaultNode=" + mFnDagNode.isDefaultNode, 3); RaiseVerbose("BabylonExporter.Mesh | mFnDagNode.isInstanceable=" + mFnDagNode.isInstanceable, 3); RaiseVerbose("BabylonExporter.Mesh | mFnDagNode.isInstanced(true)=" + mFnDagNode.isInstanced(true), 3); RaiseVerbose("BabylonExporter.Mesh | mFnDagNode.isInstanced(false)=" + mFnDagNode.isInstanced(false), 3); RaiseVerbose("BabylonExporter.Mesh | mFnDagNode.isInstanced()=" + mFnDagNode.isInstanced(), 3); RaiseVerbose("BabylonExporter.Mesh | mFnDagNode.instanceCount(true)=" + mFnDagNode.instanceCount(true), 3); RaiseVerbose("BabylonExporter.Mesh | mFnDagNode.instanceCount(false)=" + mFnDagNode.instanceCount(false), 3); RaiseVerbose("BabylonExporter.Mesh | mFnDagNode.isIntermediateObject=" + mFnDagNode.isIntermediateObject, 3); RaiseVerbose("BabylonExporter.Mesh | mFnDagNode.isShared=" + mFnDagNode.isShared, 3); RaiseVerbose("BabylonExporter.Mesh | mFnDagNode.objectColor=" + mFnDagNode.objectColor, 3); RaiseVerbose("BabylonExporter.Mesh | mFnDagNode.parentCount=" + mFnDagNode.parentCount, 3); RaiseVerbose("BabylonExporter.Mesh | mFnDagNode.parentNamespace=" + mFnDagNode.parentNamespace, 3); RaiseVerbose("BabylonExporter.Mesh | mFnDagNode.uuid().asString()=" + mFnDagNode.uuid().asString(), 3); RaiseVerbose("BabylonExporter.Mesh | mFnDagNode.dagRoot().apiType=" + mFnDagNode.dagRoot().apiType, 3); RaiseVerbose("BabylonExporter.Mesh | mFnDagNode.model.equalEqual(mFnDagNode.objectProperty)=" + mFnDagNode.model.equalEqual(mFnDagNode.objectProperty), 3); RaiseVerbose("BabylonExporter.Mesh | mFnDagNode.transformationMatrix.toString()=" + mFnDagNode.transformationMatrix.toString(), 3); }; Action <MFnMesh> printMFnMesh = (MFnMesh _mFnMesh) => { printMFnDagNode(mFnMesh); RaiseVerbose("BabylonExporter.Mesh | _mFnMesh.numVertices=" + _mFnMesh.numVertices, 3); RaiseVerbose("BabylonExporter.Mesh | _mFnMesh.numEdges=" + _mFnMesh.numEdges, 3); RaiseVerbose("BabylonExporter.Mesh | _mFnMesh.numPolygons=" + _mFnMesh.numPolygons, 3); RaiseVerbose("BabylonExporter.Mesh | _mFnMesh.numFaceVertices=" + _mFnMesh.numFaceVertices, 3); RaiseVerbose("BabylonExporter.Mesh | _mFnMesh.numNormals=" + _mFnMesh.numNormals, 3); RaiseVerbose("BabylonExporter.Mesh | _mFnMesh.numUVSets=" + _mFnMesh.numUVSets, 3); RaiseVerbose("BabylonExporter.Mesh | _mFnMesh.numUVsProperty=" + _mFnMesh.numUVsProperty, 3); RaiseVerbose("BabylonExporter.Mesh | _mFnMesh.displayColors=" + _mFnMesh.displayColors, 3); RaiseVerbose("BabylonExporter.Mesh | _mFnMesh.numColorSets=" + _mFnMesh.numColorSets, 3); RaiseVerbose("BabylonExporter.Mesh | _mFnMesh.numColorsProperty=" + _mFnMesh.numColorsProperty, 3); RaiseVerbose("BabylonExporter.Mesh | _mFnMesh.currentUVSetName()=" + _mFnMesh.currentUVSetName(), 3); var _uvSetNames = new MStringArray(); mFnMesh.getUVSetNames(_uvSetNames); foreach (var uvSetName in _uvSetNames) { RaiseVerbose("BabylonExporter.Mesh | uvSetName=" + uvSetName, 3); RaiseVerbose("BabylonExporter.Mesh | mFnMesh.numUVs(uvSetName)=" + mFnMesh.numUVs(uvSetName), 4); MFloatArray us = new MFloatArray(); MFloatArray vs = new MFloatArray(); mFnMesh.getUVs(us, vs, uvSetName); RaiseVerbose("BabylonExporter.Mesh | us.Count=" + us.Count, 4); } }; Action <MFnTransform> printMFnTransform = (MFnTransform _mFnMesh) => { printMFnDagNode(mFnMesh); }; RaiseVerbose("BabylonExporter.Mesh | mFnMesh data", 2); printMFnMesh(mFnMesh); RaiseVerbose("BabylonExporter.Mesh | mFnTransform data", 2); printMFnTransform(mFnTransform); Print(mFnTransform, 2, "Print ExportMesh mFnTransform"); Print(mFnMesh, 2, "Print ExportMesh mFnMesh"); //// Geometry //MIntArray triangleCounts = new MIntArray(); //MIntArray trianglesVertices = new MIntArray(); //mFnMesh.getTriangles(triangleCounts, trianglesVertices); //RaiseVerbose("BabylonExporter.Mesh | triangleCounts.ToArray()=" + triangleCounts.ToArray().toString(), 3); //RaiseVerbose("BabylonExporter.Mesh | trianglesVertices.ToArray()=" + trianglesVertices.ToArray().toString(), 3); //int[] polygonsVertexCount = new int[mFnMesh.numPolygons]; //for (int polygonId = 0; polygonId < mFnMesh.numPolygons; polygonId++) //{ // polygonsVertexCount[polygonId] = mFnMesh.polygonVertexCount(polygonId); //} //RaiseVerbose("BabylonExporter.Mesh | polygonsVertexCount=" + polygonsVertexCount.toString(), 3); ////MFloatPointArray points = new MFloatPointArray(); ////mFnMesh.getPoints(points); ////RaiseVerbose("BabylonExporter.Mesh | points.ToArray()=" + points.ToArray().Select(mFloatPoint => mFloatPoint.toString()), 3); ////MFloatVectorArray normals = new MFloatVectorArray(); ////mFnMesh.getNormals(normals); ////RaiseVerbose("BabylonExporter.Mesh | normals.ToArray()=" + normals.ToArray().Select(mFloatPoint => mFloatPoint.toString()), 3); //for (int polygonId = 0; polygonId < mFnMesh.numPolygons; polygonId++) //{ // MIntArray verticesId = new MIntArray(); // RaiseVerbose("BabylonExporter.Mesh | polygonId=" + polygonId, 3); // int nbTriangles = triangleCounts[polygonId]; // RaiseVerbose("BabylonExporter.Mesh | nbTriangles=" + nbTriangles, 3); // for (int triangleIndex = 0; triangleIndex < triangleCounts[polygonId]; triangleIndex++) // { // RaiseVerbose("BabylonExporter.Mesh | triangleIndex=" + triangleIndex, 3); // int[] triangleVertices = new int[3]; // mFnMesh.getPolygonTriangleVertices(polygonId, triangleIndex, triangleVertices); // RaiseVerbose("BabylonExporter.Mesh | triangleVertices=" + triangleVertices.toString(), 3); // foreach (int vertexId in triangleVertices) // { // RaiseVerbose("BabylonExporter.Mesh | vertexId=" + vertexId, 3); // MPoint point = new MPoint(); // mFnMesh.getPoint(vertexId, point); // RaiseVerbose("BabylonExporter.Mesh | point=" + point.toString(), 3); // MVector normal = new MVector(); // mFnMesh.getFaceVertexNormal(polygonId, vertexId, normal); // RaiseVerbose("BabylonExporter.Mesh | normal=" + normal.toString(), 3); // } // } //} #endregion if (IsMeshExportable(mFnMesh, mDagPath) == false) { return(null); } var babylonMesh = new BabylonMesh { name = mFnTransform.name, id = mFnTransform.uuid().asString(), visibility = Loader.GetVisibility(mFnTransform.fullPathName) }; // Instance // For a mesh with instances, we distinguish between master and instance meshes: // - a master mesh stores all the info of the mesh (transform, hierarchy, animations + vertices, indices, materials, bones...) // - an instance mesh only stores the info of the node (transform, hierarchy, animations) // Check if this mesh has already been exported as a master mesh BabylonMesh babylonMasterMesh = GetMasterMesh(mFnMesh, babylonMesh); if (babylonMasterMesh != null) { RaiseMessage($"The master mesh {babylonMasterMesh.name} was already exported. This one will be exported as an instance.", 2); // Export this node as instance var babylonInstanceMesh = new BabylonAbstractMesh { name = mFnTransform.name, id = mFnTransform.uuid().asString() }; //// Add instance to master mesh List <BabylonAbstractMesh> instances = babylonMasterMesh.instances != null?babylonMasterMesh.instances.ToList() : new List <BabylonAbstractMesh>(); instances.Add(babylonInstanceMesh); babylonMasterMesh.instances = instances.ToArray(); // Export transform / hierarchy / animations ExportNode(babylonInstanceMesh, mFnTransform, babylonScene); // Animations ExportNodeAnimation(babylonInstanceMesh, mFnTransform); return(babylonInstanceMesh); } // Position / rotation / scaling / hierarchy ExportNode(babylonMesh, mFnTransform, babylonScene); // Misc. // TODO - Retreive from Maya //babylonMesh.receiveShadows = meshNode.MaxNode.RcvShadows == 1; //babylonMesh.applyFog = meshNode.MaxNode.ApplyAtmospherics == 1; if (mFnMesh.numPolygons < 1) { RaiseError($"Mesh {babylonMesh.name} has no face", 2); } if (mFnMesh.numVertices < 3) { RaiseError($"Mesh {babylonMesh.name} has not enough vertices", 2); } if (mFnMesh.numVertices >= 65536) { RaiseWarning($"Mesh {babylonMesh.name} has more than 65536 vertices which means that it will require specific WebGL extension to be rendered. This may impact portability of your scene on low end devices.", 2); } // Animations ExportNodeAnimation(babylonMesh, mFnTransform); // Material MObjectArray shaders = new MObjectArray(); mFnMesh.getConnectedShaders(0, shaders, new MIntArray()); if (shaders.Count > 0) { List <MFnDependencyNode> materials = new List <MFnDependencyNode>(); foreach (MObject shader in shaders) { // Retreive material MFnDependencyNode shadingEngine = new MFnDependencyNode(shader); MPlug mPlugSurfaceShader = shadingEngine.findPlug("surfaceShader"); MObject materialObject = mPlugSurfaceShader.source.node; MFnDependencyNode material = new MFnDependencyNode(materialObject); materials.Add(material); } if (shaders.Count == 1) { MFnDependencyNode material = materials[0]; // Material is referenced by id babylonMesh.materialId = material.uuid().asString(); // Register material for export if not already done if (!referencedMaterials.Contains(material, new MFnDependencyNodeEqualityComparer())) { referencedMaterials.Add(material); } } else { // Create a new id for the group of sub materials string uuidMultiMaterial = GetMultimaterialUUID(materials); // Multi material is referenced by id babylonMesh.materialId = uuidMultiMaterial; // Register multi material for export if not already done if (!multiMaterials.ContainsKey(uuidMultiMaterial)) { multiMaterials.Add(uuidMultiMaterial, materials); } } } var vertices = new List <GlobalVertex>(); var indices = new List <int>(); var uvSetNames = new MStringArray(); mFnMesh.getUVSetNames(uvSetNames); bool[] isUVExportSuccess = new bool[Math.Min(uvSetNames.Count, 2)]; for (int indexUVSet = 0; indexUVSet < isUVExportSuccess.Length; indexUVSet++) { isUVExportSuccess[indexUVSet] = true; } // skin if (_exportSkin) { mFnSkinCluster = getMFnSkinCluster(mFnMesh); } int maxNbBones = 0; if (mFnSkinCluster != null) { RaiseMessage($"mFnSkinCluster.name | {mFnSkinCluster.name}", 2); Print(mFnSkinCluster, 3, $"Print {mFnSkinCluster.name}"); // Get the bones dictionary<name, index> => it represents all the bones in the skeleton indexByNodeName = GetIndexByFullPathNameDictionary(mFnSkinCluster); // Get the joint names that influence this mesh allMayaInfluenceNames = GetBoneFullPathName(mFnSkinCluster, mFnTransform); // Get the max number of joints acting on a vertex int maxNumInfluences = GetMaxInfluence(mFnSkinCluster, mFnTransform, mFnMesh); RaiseMessage($"Max influences : {maxNumInfluences}", 2); if (maxNumInfluences > 8) { RaiseWarning($"Too many bones influences per vertex: {maxNumInfluences}. Babylon.js only support up to 8 bones influences per vertex.", 2); RaiseWarning("The result may not be as expected.", 2); } maxNbBones = Math.Min(maxNumInfluences, 8); if (indexByNodeName != null && allMayaInfluenceNames != null) { babylonMesh.skeletonId = GetSkeletonIndex(mFnSkinCluster); } else { mFnSkinCluster = null; } } // Export tangents if option is checked and mesh have tangents bool isTangentExportSuccess = _exportTangents; // TODO - color, alpha //var hasColor = unskinnedMesh.NumberOfColorVerts > 0; //var hasAlpha = unskinnedMesh.GetNumberOfMapVerts(-2) > 0; // TODO - Add custom properties //var optimizeVertices = false; // meshNode.MaxNode.GetBoolProperty("babylonjs_optimizevertices"); var optimizeVertices = _optimizeVertices; // global option // Compute normals var subMeshes = new List <BabylonSubMesh>(); ExtractGeometry(mFnMesh, vertices, indices, subMeshes, uvSetNames, ref isUVExportSuccess, ref isTangentExportSuccess, optimizeVertices); if (vertices.Count >= 65536) { RaiseWarning($"Mesh {babylonMesh.name} has {vertices.Count} vertices. This may prevent your scene to work on low end devices where 32 bits indice are not supported", 2); if (!optimizeVertices) { RaiseError("You can try to optimize your object using [Try to optimize vertices] option", 2); } } for (int indexUVSet = 0; indexUVSet < isUVExportSuccess.Length; indexUVSet++) { string uvSetName = uvSetNames[indexUVSet]; // If at least one vertex is mapped to an UV coordinate but some have failed to be exported if (isUVExportSuccess[indexUVSet] == false && mFnMesh.numUVs(uvSetName) > 0) { RaiseWarning($"Failed to export UV set named {uvSetName}. Ensure all vertices are mapped to a UV coordinate.", 2); } } RaiseMessage($"{vertices.Count} vertices, {indices.Count / 3} faces", 2); // Buffers babylonMesh.positions = vertices.SelectMany(v => v.Position).ToArray(); babylonMesh.normals = vertices.SelectMany(v => v.Normal).ToArray(); // export the skin if (mFnSkinCluster != null) { babylonMesh.matricesWeights = vertices.SelectMany(v => v.Weights.ToArray()).ToArray(); babylonMesh.matricesIndices = vertices.Select(v => v.BonesIndices).ToArray(); babylonMesh.numBoneInfluencers = maxNbBones; if (maxNbBones > 4) { babylonMesh.matricesWeightsExtra = vertices.SelectMany(v => v.WeightsExtra != null ? v.WeightsExtra.ToArray() : new[] { 0.0f, 0.0f, 0.0f, 0.0f }).ToArray(); babylonMesh.matricesIndicesExtra = vertices.Select(v => v.BonesIndicesExtra).ToArray(); } } // Tangent if (isTangentExportSuccess) { babylonMesh.tangents = vertices.SelectMany(v => v.Tangent).ToArray(); } // Color string colorSetName; mFnMesh.getCurrentColorSetName(out colorSetName); if (mFnMesh.numColors(colorSetName) > 0) { babylonMesh.colors = vertices.SelectMany(v => v.Color).ToArray(); } // UVs if (uvSetNames.Count > 0 && isUVExportSuccess[0]) { babylonMesh.uvs = vertices.SelectMany(v => v.UV).ToArray(); } if (uvSetNames.Count > 1 && isUVExportSuccess[1]) { babylonMesh.uvs2 = vertices.SelectMany(v => v.UV2).ToArray(); } babylonMesh.subMeshes = subMeshes.ToArray(); // Buffers - Indices babylonMesh.indices = indices.ToArray(); babylonScene.MeshesList.Add(babylonMesh); RaiseMessage("BabylonExporter.Mesh | done", 2); return(babylonMesh); }
// // Description // // Creates a geometry iterator compatible with his shape. // // Arguments // // componentList - list of components to be iterated // components - component to be iterator // forReadOnly - // // Returns // // An iterator for the components // // Associates a user defined iterator with the shape (components) // public override MPxGeometryIterator geometryIteratorSetup( MObjectArray componentList, MObject components, bool forReadOnly = false) { apiMeshGeomIterator result = null; if ( components.isNull ) { result = new apiMeshGeomIterator( meshGeom(), componentList ); } else { result = new apiMeshGeomIterator( meshGeom(), components ); } return result; }
///////////////////////////////////////////////////////////////////// // // Overrides // ///////////////////////////////////////////////////////////////////// public override void getDrawRequests(MDrawInfo info, bool objectAndActiveOnly, MDrawRequestQueue queue) // // Description: // // Add draw requests to the draw queue // // Arguments: // // info - current drawing state // objectsAndActiveOnly - no components if true // queue - queue of draw requests to add to // { // Get the data necessary to draw the shape // MDrawData data = new MDrawData(); apiMesh meshNode = (apiMesh)surfaceShape; apiMeshGeom geom = meshNode.meshGeom(); if ((null == geom) || (0 == geom.faceCount)) { MGlobal.displayInfo("NO DrawRequest for apiMesh"); return; } // This call creates a prototype draw request that we can fill // in and then add to the draw queue. // MDrawRequest request = getDrawRequest(info); // info.getPrototype(this); getDrawData(geom, 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; // Are we displaying meshes? if (!info.objectDisplayStatus(M3dView.DisplayObjects.kDisplayMeshes)) { return; } // Use this code to help speed up drawing. // inUserInteraction() is true for any interaction with // the viewport, including object or component TRS and camera changes. // userChangingViewContext() is true only when the user is using view // context tools (tumble, dolly, track, etc.) // if (info.inUserInteraction || info.userChangingViewContext) { // User is using view context tools so // request fast draw and get out // request.token = (int)DrawToken.kDrawRedPointAtCenter; queue.add(request); return; } switch (appearance) { case M3dView.DisplayStyle.kWireFrame: { request.token = (int)DrawToken.kDrawWireframe; int activeColorTable = (int)M3dView.ColorTable.kActiveColors; int dormantColorTable = (int)M3dView.ColorTable.kDormantColors; switch (displayStatus) { case M3dView.DisplayStatus.kLead: request.setColor(LEAD_COLOR, activeColorTable); break; case M3dView.DisplayStatus.kActive: request.setColor(ACTIVE_COLOR, activeColorTable); break; case M3dView.DisplayStatus.kActiveAffected: request.setColor(ACTIVE_AFFECTED_COLOR, activeColorTable); break; case M3dView.DisplayStatus.kDormant: request.setColor(DORMANT_COLOR, dormantColorTable); break; case M3dView.DisplayStatus.kHilite: request.setColor(HILITE_COLOR, activeColorTable); break; default: break; } queue.add(request); break; } case M3dView.DisplayStyle.kGouraudShaded: { // Create the smooth shaded draw request // request.token = (int)DrawToken.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); // If the user currently has the default material enabled on the // view then use the default material for shading. // if (view.usingDefaultMaterial) { material = MMaterial.defaultMaterial; } // 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; // request.setDisplayStyle( appearance ); 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 = getDrawRequest(info); // info.getPrototype(this); wireRequest.setDrawData(data); wireRequest.token = (int)DrawToken.kDrawWireframeOnShaded; wireRequest.displayStyle = M3dView.DisplayStyle.kWireFrame; int activeColorTable = (int)M3dView.ColorTable.kActiveColors; switch (displayStatus) { case M3dView.DisplayStatus.kLead: wireRequest.setColor(LEAD_COLOR, activeColorTable); break; case M3dView.DisplayStatus.kActive: wireRequest.setColor(ACTIVE_COLOR, activeColorTable); break; case M3dView.DisplayStatus.kHilite: wireRequest.setColor(HILITE_COLOR, activeColorTable); break; default: break; } queue.add(wireRequest); } break; } case M3dView.DisplayStyle.kFlatShaded: request.token = (int)DrawToken.kDrawFlatShaded; queue.add(request); break; case M3dView.DisplayStyle.kBoundingBox: request.token = (int)DrawToken.kDrawBoundingBox; queue.add(request); break; default: break; } // Add draw requests for components // if (!objectAndActiveOnly) { // Inactive components // if ((appearance == M3dView.DisplayStyle.kPoints) || (displayStatus == M3dView.DisplayStatus.kHilite)) { MDrawRequest vertexRequest = getDrawRequest(info); // info.getPrototype(this); vertexRequest.setDrawData(data); vertexRequest.token = (int)DrawToken.kDrawVertices; vertexRequest.setColor(DORMANT_VERTEX_COLOR, (int)M3dView.ColorTable.kActiveColors); queue.add(vertexRequest); } // Active components // if (((MPxSurfaceShape)surfaceShape).hasActiveComponents) { MDrawRequest activeVertexRequest = getDrawRequest(info); // info.getPrototype(this); activeVertexRequest.setDrawData(data); activeVertexRequest.token = (int)DrawToken.kDrawVertices; activeVertexRequest.setColor(ACTIVE_VERTEX_COLOR, (int)M3dView.ColorTable.kActiveColors); MObjectArray clist = ((MPxSurfaceShape)surfaceShape).activeComponents; MObject vertexComponent = clist[0]; // Should filter list activeVertexRequest.component = vertexComponent; queue.add(activeVertexRequest); } } }
public override void glBind(MDagPath shapePath) { // ONLY push and pop required attributes performance reasons... // OpenGL.glPushAttrib(OpenGL.GL_LIGHTING_BIT); lightingOn = OpenGL.glIsEnabled(OpenGL.GL_LIGHTING); if (lightingOn > 0) { OpenGL.glEnable(OpenGL.GL_COLOR_MATERIAL); OpenGL.glColorMaterial(OpenGL.GL_FRONT_AND_BACK, OpenGL.GL_DIFFUSE); } // Base colour is always white OpenGL.glColor4f(1.0f, 1.0f, 1.0f, 1.0f); // Bind texture if(libOpenMayaNet.MAYA_API_VERSION >= 800) { MObject l_object = shapePath.node; MFnMesh mesh = new MFnMesh(l_object); String uvSetName = "map1"; MObjectArray textures = new MObjectArray(); boundTexture = false; mesh.getAssociatedUVSetTextures(uvSetName, textures); if (textures.length > 0) { MImageFileInfo.MHwTextureType hwType = new MImageFileInfo.MHwTextureType(); MHwTextureManager.glBind(textures[0], ref hwType); boundTexture = true; } if( !boundTexture) { OpenGL.glDisable(OpenGL.GL_TEXTURE_2D); OpenGL.glBindTexture(OpenGL.GL_TEXTURE_2D, 0); } } else { // To get this code branch to compile, replace <change file name here> // with an appropriate file name if (id == 0) { MImage fileImage = new MImage(); fileImage.readFromFile("<change file name here>"); uint[] param = new uint[1]; OpenGL.glGenTextures(1, param); id = param[0]; OpenGL.glEnable(OpenGL.GL_TEXTURE_2D); OpenGL.glBindTexture(OpenGL.GL_TEXTURE_2D, id); unsafe { uint width = 0, height = 0; fileImage.getSize(out width, out height); byte* pPixels = fileImage.pixels(); OpenGL.glTexImage2D(OpenGL.GL_TEXTURE_2D, 0, (int)OpenGL.GL_RGBA8, (int)width, (int)height, 0, OpenGL.GL_RGBA, OpenGL.GL_UNSIGNED_BYTE, pPixels); } } else { OpenGL.glEnable(OpenGL.GL_TEXTURE_2D); OpenGL.glBindTexture(OpenGL.GL_TEXTURE_2D, id); } boundTexture = true; } if( boundTexture) { OpenGL.glTexParameteri(OpenGL.GL_TEXTURE_2D, OpenGL.GL_TEXTURE_WRAP_S, (int)OpenGL.GL_REPEAT); OpenGL.glTexParameteri(OpenGL.GL_TEXTURE_2D, OpenGL.GL_TEXTURE_WRAP_T, (int)OpenGL.GL_REPEAT); OpenGL.glTexParameteri(OpenGL.GL_TEXTURE_2D, OpenGL.GL_TEXTURE_MIN_FILTER, (int)OpenGL.GL_LINEAR); OpenGL.glTexParameteri(OpenGL.GL_TEXTURE_2D, OpenGL.GL_TEXTURE_MAG_FILTER, (int)OpenGL.GL_LINEAR); } OpenGL.glEnableClientState(OpenGL.GL_VERTEX_ARRAY); return; }
public override void tweakUsing( MMatrix mat, MObjectArray componentList, MVertexCachingMode cachingMode, MPointArray pointCache, MArrayDataHandle handle ) // // Description // // Transforms the given components. This method is used by // the move, rotate, and scale tools in component mode when the // tweaks for the shape are stored on a separate tweak node. // The bounding box has to be updated here, so do the normals and // any other attributes that depend on vertex positions. // // Arguments // mat - matrix to transform the components by // componentList - list of components to be transformed, // or an empty list to indicate the whole surface // cachingMode - how to use the supplied pointCache // pointCache - if non-null, save or restore points from this list base // on the cachingMode // handle - handle to the attribute on the tweak node where the // tweaks should be stored // { apiMeshGeom geomPtr = meshGeom(); bool savePoints = (cachingMode == MVertexCachingMode.kSavePoints); bool updatePoints = (cachingMode == MVertexCachingMode.kUpdatePoints); MArrayDataBuilder builder = handle.builder(); MPoint delta = new MPoint(); MPoint currPt = new MPoint(); MPoint newPt = new MPoint(); int i=0; uint len = componentList.length; int cacheIndex = 0; uint cacheLen = (null != pointCache) ? pointCache.length : 0; if (cachingMode == MVertexCachingMode.kRestorePoints) { // restore points from the pointCache // if (len > 0) { // traverse the component list // for ( i=0; i<len; i++ ) { MObject comp = componentList[i]; MFnSingleIndexedComponent fnComp = new MFnSingleIndexedComponent( comp ); int elemCount = fnComp.elementCount; for ( int idx=0; idx<elemCount && cacheIndex < cacheLen; idx++, cacheIndex++) { int elemIndex = fnComp.element( idx ); MDataHandle hdl = builder.addElement((uint)elemIndex); double[] pt = hdl.Double3; MPoint cachePt = pointCache[cacheIndex]; pt[0] += cachePt.x; pt[1] += cachePt.y; pt[2] += cachePt.z; hdl.Double3 = pt; } } } else { // if the component list is of zero-length, it indicates that we // should transform the entire surface // len = geomPtr.vertices.length; for ( uint idx = 0; idx < len && idx < cacheLen; ++idx ) { MDataHandle hdl = builder.addElement(idx); double[] pt = hdl.Double3; MPoint cachePt = pointCache[cacheIndex]; pt[0] += cachePt.x; pt[1] += cachePt.y; pt[2] += cachePt.z; hdl.Double3 = pt; } } } else { // Tweak the points. If savePoints is true, also save the tweaks in the // pointCache. If updatePoints is true, add the new tweaks to the existing // data in the pointCache. // if (len > 0) { for ( i=0; i<len; i++ ) { MObject comp = componentList[i]; MFnSingleIndexedComponent fnComp = new MFnSingleIndexedComponent( comp ); int elemCount = fnComp.elementCount; if (savePoints) { pointCache.sizeIncrement = (uint)elemCount; } for ( int idx=0; idx<elemCount; idx++ ) { int elemIndex = fnComp.element( idx ); MDataHandle hdl = builder.addElement((uint)elemIndex); double[] pt = hdl.Double3; currPt = newPt = geomPtr.vertices[elemIndex]; newPt.multiplyEqual( mat ); delta.x = newPt.x - currPt.x; delta.y = newPt.y - currPt.y; delta.z = newPt.z - currPt.z; pt[0] += delta.x; pt[1] += delta.y; pt[2] += delta.z; hdl.Double3 = pt; if (savePoints) { // store the points in the pointCache for undo // pointCache.append(delta*(-1.0)); } else if (updatePoints && cacheIndex < cacheLen) { MPoint cachePt = pointCache[cacheIndex]; cachePt[0] -= delta.x; cachePt[1] -= delta.y; cachePt[2] -= delta.z; cacheIndex++; } } } } else { // if the component list is of zero-length, it indicates that we // should transform the entire surface // len = geomPtr.vertices.length; if (savePoints) { pointCache.sizeIncrement = len; } for ( int idx = 0; idx < len; ++idx ) { MDataHandle hdl = builder.addElement((uint)idx); double[] pt = hdl.Double3; currPt = newPt = geomPtr.vertices[idx]; newPt.multiplyEqual( mat ); delta.x = newPt.x - currPt.x; delta.y = newPt.y - currPt.y; delta.z = newPt.z - currPt.z; pt[0] += delta.x; pt[1] += delta.y; pt[2] += delta.z; hdl.Double3 = pt; if (savePoints) { // store the points in the pointCache for undo // pointCache.append(delta*-1.0); } else if (updatePoints && idx < cacheLen) { MPoint cachePt = pointCache[idx]; cachePt[0] -= delta.x; cachePt[1] -= delta.y; cachePt[2] -= delta.z; } } } } // Set the builder into the handle. // handle.set(builder); // Tell Maya the bounding box for this object has changed // and thus "boundingBox()" needs to be called. // childChanged( MChildChanged.kBoundingBoxChanged ); }
// // Description: // Overloaded function from MPxDragAndDropBehavior // this method will handle the connection between the slopeShaderNodeCSharp and the shader it is // assigned to as well as any meshes that it is assigned to. // public override void connectNodeToNode(MObject sourceNode, MObject destinationNode, bool force) { MFnDependencyNode src = new MFnDependencyNode(sourceNode); //if we are dragging from a lambert //we want to check what we are dragging //onto. if (sourceNode.hasFn(MFn.Type.kLambert)) { //MObject shaderNode; MPlugArray connections = new MPlugArray(); MObjectArray shaderNodes = new MObjectArray(); shaderNodes.clear(); //if the source node was a lambert //than we will check the downstream connections to see //if a slope shader is assigned to it. // src.getConnections(connections); int i; for (i = 0; i < connections.length; i++) { //check the incoming connections to this plug // MPlugArray connectedPlugs = new MPlugArray(); connections[i].connectedTo(connectedPlugs, true, false); for (uint j = 0; j < connectedPlugs.length; j++) { //if the incoming node is a slope shader than //append the node to the shaderNodes array // MObject currentnode = connectedPlugs[i].node; if (new MFnDependencyNode(currentnode).typeName == "slopeShaderNodeCSharp") { shaderNodes.append(currentnode); } } } //if we found a shading node //than check the destination node //type to see if it is a mesh // if (shaderNodes.length > 0) { MFnDependencyNode dest = new MFnDependencyNode(destinationNode); if (destinationNode.hasFn(MFn.Type.kMesh)) { //if the node is a mesh than for each slopeShaderNodeCSharp //connect the worldMesh attribute to the dirtyShaderPlug //attribute to force an evaluation of the node when the mesh //changes // for (i = 0; i < shaderNodes.length; i++) { MPlug srcPlug = dest.findPlug("worldMesh"); MPlug destPlug = new MFnDependencyNode(shaderNodes[i]).findPlug("dirtyShaderPlug"); if (!srcPlug.isNull && !destPlug.isNull) { string cmd = "connectAttr -na "; cmd += srcPlug.name + " "; cmd += destPlug.name; try { // in slopeShaderBehavior.cpp, this may excute failed but continue on the following code, so we catch it. MGlobal.executeCommand(cmd); } catch (System.Exception) { MGlobal.displayError("ExcuteCommand (" + cmd + ") failed."); } } } //get the shading engine so we can assign the shader //to the mesh after doing the connection // MObject shadingEngine = findShadingEngine(sourceNode); //if there is a valid shading engine than make //the connection // if (!shadingEngine.isNull) { string cmd = "sets -edit -forceElement "; cmd += new MFnDependencyNode(shadingEngine).name + " "; cmd += new MFnDagNode(destinationNode).partialPathName; MGlobal.executeCommand(cmd); } } } } else if (src.typeName == "slopeShaderNodeCSharp") //if we are dragging from a slope shader //than we want to see what we are dragging onto // { if (destinationNode.hasFn(MFn.Type.kMesh)) { //if the user is dragging onto a mesh //than make the connection from the worldMesh //to the dirtyShader plug on the slopeShaderNodeCSharp // MFnDependencyNode dest = new MFnDependencyNode(destinationNode); MPlug srcPlug = dest.findPlug("worldMesh"); MPlug destPlug = src.findPlug("dirtyShaderPlug"); if (!srcPlug.isNull && !destPlug.isNull) { string cmd = "connectAttr -na "; cmd += srcPlug.name + " "; cmd += destPlug.name; MGlobal.executeCommand(cmd); } } } return; }
private void dumpInfo(MObject fileNode, MFnDependencyNode nodeFn, MObjectArray nodePath) { MObject fileAttr = nodeFn.attribute("fileTextureName"); MPlug plugToFile = new MPlug(fileNode, fileAttr); MFnDependencyNode dgFn = new MFnDependencyNode(); MGlobal.displayInfo("Name: " + nodeFn.name); MObject fnameValue = new MObject(); try { plugToFile.getValue(fnameValue); } catch (Exception) { MGlobal.displayInfo("error getting value from plug"); return; } MFnStringData stringFn = new MFnStringData(fnameValue); MGlobal.displayInfo("Texture: " + stringFn.stringProperty); string path = "Path: "; for (int i = (int)nodePath.length - 1; i >= 0; i--) { MObject currentNode = nodePath[i]; dgFn.setObject(currentNode); path += dgFn.name + "(" + dgFn.typeName + ")"; if (i > 0) path += " -> "; } MGlobal.displayInfo(path); }
public override void doIt(MArgList args) { MSelectionList list = new MSelectionList(); if (args.length > 0) { // Arg list is > 0 so use objects that were passes in // uint last = args.length; for (uint i = 0; i < last; i++) { // Attempt to find all of the objects matched // by the string and add them to the list // string argStr = args.asString(i); list.add(argStr); } } else { // Get arguments from Maya's selection list. MGlobal.getActiveSelectionList(list); } MObject node = new MObject(); MObjectArray nodePath = new MObjectArray(); MFnDependencyNode nodeFn = new MFnDependencyNode(); MFnDependencyNode dgNodeFnSet = new MFnDependencyNode(); for (MItSelectionList iter = new MItSelectionList(list); !iter.isDone; iter.next()) { iter.getDependNode(node); // // The following code shows how to navigate the DG manually without // using an iterator. First, find the attribute that you are // interested. Then connect a plug to it and see where the plug // connected to. Once you get all the connections, you can choose // which route you want to go. // // In here, we wanted to get to the nodes that instObjGroups connected // to since we know that the shadingEngine connects to the instObjGroup // attribute. // nodeFn.setObject(node); MObject iogAttr = null; try { iogAttr = nodeFn.attribute("instObjGroups"); } catch (Exception) { MGlobal.displayInfo(nodeFn.name + ": is not a renderable object, skipping"); continue; } MPlug iogPlug = new MPlug(node, iogAttr); MPlugArray iogConnections = new MPlugArray(); // // instObjGroups is a multi attribute. In this example, just the // first connection will be tried. // if (!iogPlug.elementByLogicalIndex(0).connectedTo(iogConnections, false, true)) { MGlobal.displayInfo(nodeFn.name + ": is not in a shading group, skipping"); continue; } // // Now we would like to traverse the DG starting from the shadingEngine // since most likely all file texture nodes will be found. Note the // filter used to initialize the DG iterator. There are lots of filter // type available in MF.Type that you can choose to suite your needs. // bool foundATexture = false; for (int i = 0; i < iogConnections.length; i++) { MObject currentNode = iogConnections[i].node; // // Note that upon initialization, the current pointer of the // iterator already points to the first valid node. // MItDependencyGraph dgIt = new MItDependencyGraph(currentNode, MFn.Type.kFileTexture, MItDependencyGraph.Direction.kUpstream, MItDependencyGraph.Traversal.kBreadthFirst, MItDependencyGraph.Level.kNodeLevel); if (dgIt == null) { continue; } dgIt.disablePruningOnFilter(); for ( ; !dgIt.isDone; dgIt.next()) { MObject thisNode = dgIt.thisNode(); dgNodeFnSet.setObject(thisNode); try { dgIt.getNodePath(nodePath); } catch (Exception) { MGlobal.displayInfo("getNodePath"); continue; } // // append the starting node. // nodePath.append(node); dumpInfo(thisNode, dgNodeFnSet, nodePath); foundATexture = true; } } if (!foundATexture) { MGlobal.displayInfo(nodeFn.name + ": is not connected to a file texture"); } } return; }
public override void glBind(MDagPath shapePath) { // ONLY push and pop required attributes performance reasons... // OpenGL.glPushAttrib(OpenGL.GL_LIGHTING_BIT); lightingOn = OpenGL.glIsEnabled(OpenGL.GL_LIGHTING); if (lightingOn > 0) { OpenGL.glEnable(OpenGL.GL_COLOR_MATERIAL); OpenGL.glColorMaterial(OpenGL.GL_FRONT_AND_BACK, OpenGL.GL_DIFFUSE); } // Base colour is always white OpenGL.glColor4f(1.0f, 1.0f, 1.0f, 1.0f); // Bind texture if (libOpenMayaNet.MAYA_API_VERSION >= 800) { MObject l_object = shapePath.node; MFnMesh mesh = new MFnMesh(l_object); String uvSetName = "map1"; MObjectArray textures = new MObjectArray(); boundTexture = false; mesh.getAssociatedUVSetTextures(uvSetName, textures); if (textures.length > 0) { MImageFileInfo.MHwTextureType hwType = new MImageFileInfo.MHwTextureType(); MHwTextureManager.glBind(textures[0], ref hwType); boundTexture = true; } if (!boundTexture) { OpenGL.glDisable(OpenGL.GL_TEXTURE_2D); OpenGL.glBindTexture(OpenGL.GL_TEXTURE_2D, 0); } } else { // To get this code branch to compile, replace <change file name here> // with an appropriate file name if (id == 0) { MImage fileImage = new MImage(); fileImage.readFromFile("<change file name here>"); uint[] param = new uint[1]; OpenGL.glGenTextures(1, param); id = param[0]; OpenGL.glEnable(OpenGL.GL_TEXTURE_2D); OpenGL.glBindTexture(OpenGL.GL_TEXTURE_2D, id); unsafe { uint width = 0, height = 0; fileImage.getSize(out width, out height); byte *pPixels = fileImage.pixels(); OpenGL.glTexImage2D(OpenGL.GL_TEXTURE_2D, 0, (int)OpenGL.GL_RGBA8, (int)width, (int)height, 0, OpenGL.GL_RGBA, OpenGL.GL_UNSIGNED_BYTE, pPixels); } } else { OpenGL.glEnable(OpenGL.GL_TEXTURE_2D); OpenGL.glBindTexture(OpenGL.GL_TEXTURE_2D, id); } boundTexture = true; } if (boundTexture) { OpenGL.glTexParameteri(OpenGL.GL_TEXTURE_2D, OpenGL.GL_TEXTURE_WRAP_S, (int)OpenGL.GL_REPEAT); OpenGL.glTexParameteri(OpenGL.GL_TEXTURE_2D, OpenGL.GL_TEXTURE_WRAP_T, (int)OpenGL.GL_REPEAT); OpenGL.glTexParameteri(OpenGL.GL_TEXTURE_2D, OpenGL.GL_TEXTURE_MIN_FILTER, (int)OpenGL.GL_LINEAR); OpenGL.glTexParameteri(OpenGL.GL_TEXTURE_2D, OpenGL.GL_TEXTURE_MAG_FILTER, (int)OpenGL.GL_LINEAR); } OpenGL.glEnableClientState(OpenGL.GL_VERTEX_ARRAY); return; }
/// <summary> /// Extract ordered indices on a triangle basis /// Extract position and normal of each vertex per face /// </summary> /// <param name="mFnMesh"></param> /// <param name="vertices"></param> /// <param name="indices"></param> /// <param name="subMeshes"></param> /// <param name="uvSetNames"></param> /// <param name="isUVExportSuccess"></param> /// <param name="optimizeVertices"></param> private void ExtractGeometry(MFnMesh mFnMesh, List <GlobalVertex> vertices, List <int> indices, List <BabylonSubMesh> subMeshes, MStringArray uvSetNames, ref bool[] isUVExportSuccess, bool optimizeVertices) { // TODO - optimizeVertices MIntArray triangleCounts = new MIntArray(); MIntArray trianglesVertices = new MIntArray(); mFnMesh.getTriangles(triangleCounts, trianglesVertices); MObjectArray shaders = new MObjectArray(); MIntArray faceMatIndices = new MIntArray(); // given a face index => get a shader index mFnMesh.getConnectedShaders(0, shaders, faceMatIndices); // Export geometry even if an error occured with shaders // This is a fix for Maya test files // TODO - Find the reason why shaders.count = 0 int nbShaders = Math.Max(1, shaders.Count); bool checkShader = nbShaders == shaders.Count; RaiseVerbose("shaders.Count=" + shaders.Count, 2); // For each material of this mesh for (int indexShader = 0; indexShader < nbShaders; indexShader++) { var nbIndicesSubMesh = 0; var minVertexIndexSubMesh = int.MaxValue; var maxVertexIndexSubMesh = int.MinValue; var subMesh = new BabylonSubMesh { indexStart = indices.Count, materialIndex = indexShader }; // For each polygon of this mesh for (int polygonId = 0; polygonId < faceMatIndices.Count; polygonId++) { if (checkShader && faceMatIndices[polygonId] != indexShader) { continue; } // The object-relative (mesh-relative/global) vertex indices for this face MIntArray polygonVertices = new MIntArray(); mFnMesh.getPolygonVertices(polygonId, polygonVertices); // For each triangle of this polygon for (int triangleId = 0; triangleId < triangleCounts[polygonId]; triangleId++) { int[] polygonTriangleVertices = new int[3]; mFnMesh.getPolygonTriangleVertices(polygonId, triangleId, polygonTriangleVertices); /* * Switch coordinate system at global level * * Piece of code kept just in case * See BabylonExporter for more information */ //// Inverse winding order to flip faces //var tmp = triangleVertices[1]; //triangleVertices[1] = triangleVertices[2]; //triangleVertices[2] = tmp; // For each vertex of this triangle (3 vertices per triangle) foreach (int vertexIndexGlobal in polygonTriangleVertices) { // Get the face-relative (local) vertex id int vertexIndexLocal = 0; for (vertexIndexLocal = 0; vertexIndexLocal < polygonVertices.Count; vertexIndexLocal++) { if (polygonVertices[vertexIndexLocal] == vertexIndexGlobal) { break; } } GlobalVertex vertex = ExtractVertex(mFnMesh, polygonId, vertexIndexGlobal, vertexIndexLocal, uvSetNames, ref isUVExportSuccess); vertex.CurrentIndex = vertices.Count; indices.Add(vertex.CurrentIndex); vertices.Add(vertex); minVertexIndexSubMesh = Math.Min(minVertexIndexSubMesh, vertex.CurrentIndex); maxVertexIndexSubMesh = Math.Max(maxVertexIndexSubMesh, vertex.CurrentIndex); nbIndicesSubMesh++; } } } if (nbIndicesSubMesh != 0) { subMesh.indexCount = nbIndicesSubMesh; subMesh.verticesStart = minVertexIndexSubMesh; subMesh.verticesCount = maxVertexIndexSubMesh - minVertexIndexSubMesh + 1; subMeshes.Add(subMesh); } } }
// Associates a user defined iterator with the shape (components) // public override MPxGeometryIterator geometryIteratorSetup( MObjectArray componentList, MObject components, bool forReadOnly = false ) // // Description // // Creates a geometry iterator compatible with his shape. // // Arguments // // componentList - list of components to be iterated // components - component to be iterator // forReadOnly - // // Returns // // An iterator for the components // { apiMeshGeomIterator result = null; if ( components.isNull ) { result = new apiMeshGeomIterator( meshGeom(), componentList ); } else { result = new apiMeshGeomIterator( meshGeom(), components ); } return result; }
// // Description // // Transforms by the matrix the given components, or the entire shape // if the componentList is empty. This method is used by the freezeTransforms command. // // Arguments // // mat - matrix to transform the components by // componentList - list of components to be transformed, // or an empty list to indicate the whole surface // // Support the translate/rotate/scale tool (components) // public override void transformUsing(MMatrix mat, MObjectArray componentList) { // Let the other version of transformUsing do the work for us. // transformUsing( mat, componentList, MVertexCachingMode.kNoPointCaching, null); }
public override bool match(MSelectionMask mask, MObjectArray componentList) // // Description: // // Check for matches between selection type / component list, and // the type of this shape / or it's components // // This is used by sets and deformers to make sure that the selected // components fall into the "vertex only" category. // // Arguments // // mask - selection type mask // componentList - possible component list // // Returns // true if matched any // { bool result = false; if( componentList.length == 0 ) { result = mask.intersects( MSelectionMask.SelectionType.kSelectMeshes ); } else { for ( int i=0; i<componentList.length; i++ ) { if ( (componentList[i].apiType == MFn.Type.kMeshVertComponent) && (mask.intersects(MSelectionMask.SelectionType.kSelectMeshVerts)) ) { result = true; break; } } } return result; }
// // Description // // Transforms the given components. This method is used by // the move, rotate, and scale tools in component mode when the // tweaks for the shape are stored on a separate tweak node. // The bounding box has to be updated here, so do the normals and // any other attributes that depend on vertex positions. // // Arguments // mat - matrix to transform the components by // componentList - list of components to be transformed, // or an empty list to indicate the whole surface // cachingMode - how to use the supplied pointCache // pointCache - if non-null, save or restore points from this list base // on the cachingMode // handle - handle to the attribute on the tweak node where the // tweaks should be stored // public override void tweakUsing( MMatrix mat, MObjectArray componentList, MVertexCachingMode cachingMode, MPointArray pointCache, MArrayDataHandle handle) { apiMeshGeom geomPtr = meshGeom(); bool savePoints = (cachingMode == MVertexCachingMode.kSavePoints); bool updatePoints = (cachingMode == MVertexCachingMode.kUpdatePoints); MArrayDataBuilder builder = handle.builder(); MPoint delta = new MPoint(); MPoint currPt = new MPoint(); MPoint newPt = new MPoint(); int i=0; uint len = componentList.length; int cacheIndex = 0; uint cacheLen = (null != pointCache) ? pointCache.length : 0; if (cachingMode == MVertexCachingMode.kRestorePoints) { // restore points from the pointCache // if (len > 0) { // traverse the component list // for ( i=0; i<len; i++ ) { MObject comp = componentList[i]; MFnSingleIndexedComponent fnComp = new MFnSingleIndexedComponent( comp ); int elemCount = fnComp.elementCount; for ( int idx=0; idx<elemCount && cacheIndex < cacheLen; idx++, cacheIndex++) { int elemIndex = fnComp.element( idx ); MDataHandle hdl = builder.addElement((uint)elemIndex); double[] pt = hdl.Double3; MPoint cachePt = pointCache[cacheIndex]; pt[0] += cachePt.x; pt[1] += cachePt.y; pt[2] += cachePt.z; hdl.Double3 = pt; } } } else { // if the component list is of zero-length, it indicates that we // should transform the entire surface // len = geomPtr.vertices.length; for ( uint idx = 0; idx < len && idx < cacheLen; ++idx ) { MDataHandle hdl = builder.addElement(idx); double[] pt = hdl.Double3; MPoint cachePt = pointCache[cacheIndex]; pt[0] += cachePt.x; pt[1] += cachePt.y; pt[2] += cachePt.z; hdl.Double3 = pt; } } } else { // Tweak the points. If savePoints is true, also save the tweaks in the // pointCache. If updatePoints is true, add the new tweaks to the existing // data in the pointCache. // if (len > 0) { for ( i=0; i<len; i++ ) { MObject comp = componentList[i]; MFnSingleIndexedComponent fnComp = new MFnSingleIndexedComponent( comp ); int elemCount = fnComp.elementCount; if (savePoints) { pointCache.sizeIncrement = (uint)elemCount; } for ( int idx=0; idx<elemCount; idx++ ) { int elemIndex = fnComp.element( idx ); MDataHandle hdl = builder.addElement((uint)elemIndex); double[] pt = hdl.Double3; currPt = newPt = geomPtr.vertices[elemIndex]; newPt.multiplyEqual( mat ); delta.x = newPt.x - currPt.x; delta.y = newPt.y - currPt.y; delta.z = newPt.z - currPt.z; pt[0] += delta.x; pt[1] += delta.y; pt[2] += delta.z; hdl.Double3 = pt; if (savePoints) { // store the points in the pointCache for undo // pointCache.append(delta*(-1.0)); } else if (updatePoints && cacheIndex < cacheLen) { MPoint cachePt = pointCache[cacheIndex]; cachePt[0] -= delta.x; cachePt[1] -= delta.y; cachePt[2] -= delta.z; cacheIndex++; } } } } else { // if the component list is of zero-length, it indicates that we // should transform the entire surface // len = geomPtr.vertices.length; if (savePoints) { pointCache.sizeIncrement = len; } for ( int idx = 0; idx < len; ++idx ) { MDataHandle hdl = builder.addElement((uint)idx); double[] pt = hdl.Double3; currPt = newPt = geomPtr.vertices[idx]; newPt.multiplyEqual( mat ); delta.x = newPt.x - currPt.x; delta.y = newPt.y - currPt.y; delta.z = newPt.z - currPt.z; pt[0] += delta.x; pt[1] += delta.y; pt[2] += delta.z; hdl.Double3 = pt; if (savePoints) { // store the points in the pointCache for undo // pointCache.append(delta*-1.0); } else if (updatePoints && idx < cacheLen) { MPoint cachePt = pointCache[idx]; cachePt[0] -= delta.x; cachePt[1] -= delta.y; cachePt[2] -= delta.z; } } } } // Set the builder into the handle. // handle.set(builder); // Tell Maya the bounding box for this object has changed // and thus "boundingBox()" needs to be called. // childChanged( MChildChanged.kBoundingBoxChanged ); }
// Support the translate/rotate/scale tool (components) // public override void transformUsing(MMatrix mat, MObjectArray componentList) // // Description // // Transforms by the matrix the given components, or the entire shape // if the componentList is empty. This method is used by the freezeTransforms command. // // Arguments // // mat - matrix to transform the components by // componentList - list of components to be transformed, // or an empty list to indicate the whole surface // { // Let the other version of transformUsing do the work for us. // transformUsing( mat, componentList, MVertexCachingMode.kNoPointCaching, null); }
// // Description: // // Check for matches between selection type / component list, and // the type of this shape / or it's components // // This is used by sets and deformers to make sure that the selected // components fall into the "vertex only" category. // // Arguments // // mask - selection type mask // componentList - possible component list // // Returns // true if matched any // public override bool match(MSelectionMask mask, MObjectArray componentList) { bool result = false; if( componentList.length == 0 ) { result = mask.intersects( MSelectionMask.SelectionType.kSelectMeshes ); } else { for ( int i=0; i<componentList.length; i++ ) { if ( (componentList[i].apiType == MFn.Type.kMeshVertComponent) && (mask.intersects(MSelectionMask.SelectionType.kSelectMeshVerts)) ) { result = true; break; } } } return result; }