public apiMeshGeomIterator(object userGeometry, MObjectArray components)
            : base(userGeometry, components)
        {
            meshGeometry = (apiMeshGeom)userGeometry;

            reset();
        }
Example #2
0
        /// <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);
        }
Example #3
0
        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);
        }
Example #4
0
		public apiMeshGeomIterator(object userGeometry, MObjectArray components)
			: base(userGeometry, components)
		{
			meshGeometry = (apiMeshGeom)userGeometry;

			reset();
		}
Example #5
0
        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));
        }
Example #6
0
		public maTranslator()
		{
			fBrokenConnSrcs = new MPlugArray();
			fBrokenConnDests = new MPlugArray();

			fDefaultNodes = new MObjectArray();

			fInstanceChildren = new MDagPathArray();
			fInstanceParents = new MDagPathArray();

			fParentingRequired = new MDagPathArray();
		}
Example #7
0
 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;
 }
Example #8
0
 //////////////////////////////////////////////////////////////////
 //
 // 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;
 }
Example #9
0
        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);
        }
Example #10
0
        /// <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.");
                }
            }
        }
Example #11
0
        //////////////////////////////////////////////////////////////////
        //
        // 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);
        }
Example #12
0
        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);
        }
Example #13
0
		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;
		}
Example #14
0
        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) ;
        }
Example #15
0
        protected AssociationsSerializer fSerialize; // Serialization format

        public metadataBase() : base()
        {
            fMode   = CommandMode.kCreate;
            fMeshes = new MObjectArray();
        }
Example #16
0
        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);
        }
Example #17
0
        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);
        }
Example #19
0
        /// <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);
        }
Example #20
0
        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;
        }
Example #21
0
        //
        //    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();
 }
Example #24
0
		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");
        }
 public apiSimpleShapeIterator(object userGeometry, MObjectArray components) :
     base(userGeometry, components)
 {
     mGeometry = userGeometry as MVectorArray;
     reset();
 }
Example #27
0
        //
        // 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);
        }
Example #29
0
 //
 // 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;
 }
Example #30
0
        /////////////////////////////////////////////////////////////////////
        //
        // 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;
        }
Example #32
0
	    protected AssociationsSerializer fSerialize; // Serialization format
        
        public metadataBase() : base()
        {
            fMode = CommandMode.kCreate;
            fMeshes = new MObjectArray();
        }
Example #33
0
		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 );
		}
Example #34
0
        //
        //	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;
        }
Example #35
0
		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);
		}
Example #36
0
        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;
        }
Example #38
0
        /// <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);
                }
            }
        }
Example #39
0
		// 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;
		}
Example #40
0
 //
 // 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);
 }
Example #41
0
		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;
		}
Example #42
0
        //
        // 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 );
        }
Example #43
0
		// 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);
		}
Example #44
0
        //
        // 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;
        }
Example #45
0
 protected override void getOutputAttributes(MObjectArray attributeArray)
 {
     attributeArray.clear();
     attributeArray.append(GeometrySurfaceConstraint.constraintGeometry);
 }