Пример #1
0
bool getObjectShadingGroups(const MDagPath& shapeObjectDP, MObject& shadingGroup)
{
    // if obj is a light, simply return the mobject
    if (shapeObjectDP.hasFn(MFn::kLight))
        shadingGroup = shapeObjectDP.node();

    if (shapeObjectDP.hasFn(MFn::kMesh))
    {
        // Find the Shading Engines Connected to the SourceNode
        MFnMesh fnMesh(shapeObjectDP.node());

        // A ShadingGroup will have a MFnSet
        MObjectArray sets, comps;
        fnMesh.getConnectedSetsAndMembers(shapeObjectDP.instanceNumber(), sets, comps, true);

        // Each set is a Shading Group. Loop through them
        for (unsigned int i = 0; i < sets.length(); ++i)
        {
            shadingGroup = sets[i];
            return true;
        }
    }

    if (shapeObjectDP.hasFn(MFn::kNurbsSurface)||shapeObjectDP.hasFn(MFn::kParticle)||shapeObjectDP.hasFn(MFn::kNParticle))
    {

        MObject instObjGroupsAttr;
        if (shapeObjectDP.hasFn(MFn::kNurbsSurface))
        {
            MFnNurbsSurface fnNurbs(shapeObjectDP.node());
            instObjGroupsAttr = fnNurbs.attribute("instObjGroups");
        }
        if (shapeObjectDP.hasFn(MFn::kParticle)||shapeObjectDP.hasFn(MFn::kNParticle))
        {
            MFnParticleSystem fnPart(shapeObjectDP.node());
            instObjGroupsAttr = fnPart.attribute("instObjGroups");
        }
        MPlug instPlug(shapeObjectDP.node(), instObjGroupsAttr);

        // Get the instance that our node is referring to;
        // In other words get the Plug for instObjGroups[intanceNumber];
        MPlug instPlugElem = instPlug.elementByLogicalIndex(shapeObjectDP.instanceNumber());

        // Find the ShadingGroup plugs that we are connected to as Source
        MPlugArray SGPlugArray;
        instPlugElem.connectedTo(SGPlugArray, false, true);

        // Loop through each ShadingGroup Plug
        for (unsigned int i=0; i < SGPlugArray.length(); ++i)
        {
            shadingGroup = SGPlugArray[i].node();
            return true;
        }
    }
    return false;
}
//-----------------------------------------------------------------------------
// This is here for reference. It isn't currently used
//-----------------------------------------------------------------------------
void CVsSkinnerCmd::DoConnectGeometry(
	const MDagPath &skinnerPath,
	const MDagPath &gDagPath )
{
	MObject skinnerObj( skinnerPath.node() );
	const MFnDependencyNode vsSkinnerFn( skinnerObj );
	const MFnMesh meshFn( gDagPath );

	// Connect things up

	MPlug sP;
	MPlug dP;

	MDagModifier &mDagModifier( m_undo.DagModifier() );

	// Connect mesh.worldMatrix[#] vsSkinner.geometryWorldMatrix
	sP = meshFn.findPlug( "worldMatrix" );
	sP = sP.elementByLogicalIndex( gDagPath.instanceNumber() );
	dP = vsSkinnerFn.findPlug( "geometryWorldMatrix" );
	mDagModifier.connect( sP, dP );

	sP = meshFn.findPlug( "outMesh" );
	dP = vsSkinnerFn.findPlug( "inputGeometry" );
	mDagModifier.connect( sP, dP );

	mDagModifier.doIt();

	// Add the default volume
	MSelectionList emptyList;
	MGlobal::setActiveSelectionList( DoNewVolumes( skinnerPath, emptyList ), MGlobal::kReplaceList );
}
Пример #3
0
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
void ConnectIntWeld( vm::CUndo &undo, const MObject &weldNodeObj, const MDagPath &toWeldPath, int nType, int nIntValue, const MMatrix &offsetMatrix )
{
	MFnDependencyNode weldFn( weldNodeObj );
	MFnDagNode toWeldFn( toWeldPath );

	MPlug wiAP = weldFn.findPlug( CVstWeldNode::m_iaWeldInput );
	const uint nWeldIndex = vm::NextAvailable( wiAP );
	MPlug wiP = wiAP.elementByLogicalIndex( nWeldIndex );

	undo.SetAttr( wiP.child( CVstWeldNode::m_iaType ), nType );
	undo.SetAttr( wiP.child( CVstWeldNode::m_iaInt ), nIntValue );

	MFnMatrixData dFn;
	MObject mdObj = dFn.create( offsetMatrix );
	undo.SetAttr( wiP.child( CVstWeldNode::m_iaOffsetMatrix ), mdObj );

	undo.Connect( toWeldFn.findPlug( "parentInverseMatrix" ).elementByLogicalIndex( toWeldPath.instanceNumber() ), wiP.child( CVstWeldNode::m_iaInverseParentSpace ), true );
	undo.Connect( toWeldFn.findPlug( "rotateOrder" ), wiP.child( CVstWeldNode::m_iaRotateOrder ), true );

	MPlug woAP = weldFn.findPlug( CVstWeldNode::m_oaWeldOutput );
	MPlug woP = woAP.elementByLogicalIndex( nWeldIndex );
	MPlug tP = woP.child( CVstWeldNode::m_oaTranslate );

	undo.Connect( tP.child( CVstWeldNode::m_oaTranslateX ), toWeldFn.findPlug( "translateX" ) );
	undo.Connect( tP.child( CVstWeldNode::m_oaTranslateY ), toWeldFn.findPlug( "translateY" ) );
	undo.Connect( tP.child( CVstWeldNode::m_oaTranslateZ ), toWeldFn.findPlug( "translateZ" ) );

	MPlug rP = woP.child( CVstWeldNode::m_oaRotate );

	undo.Connect( rP.child( CVstWeldNode::m_oaRotateX ), toWeldFn.findPlug( "rotateX" ) );
	undo.Connect( rP.child( CVstWeldNode::m_oaRotateY ), toWeldFn.findPlug( "rotateY" ) );
	undo.Connect( rP.child( CVstWeldNode::m_oaRotateZ ), toWeldFn.findPlug( "rotateZ" ) );
}
    // --------------------------------------------------------------------
    MStatus SceneGraph::addInstancedDagPaths ( MSelectionList& selectionList )
    {
        MStatus status;
        int length = selectionList.length ( &status );
        if ( status != MStatus::kSuccess ) return MStatus::kFailure;

        for ( int i=0; i<length; i++ )
        {
            MDagPath dagPath;
            if ( selectionList.getDagPath ( i, dagPath ) != MStatus::kSuccess ) return MStatus::kFailure;

            if ( dagPath.isInstanced() )
            {
                int includedInstance=dagPath.instanceNumber ( &status );
                if ( status != MStatus::kSuccess ) return MStatus::kFailure;

                MObject object=dagPath.node ( &status );
                if ( status != MStatus::kSuccess ) return MStatus::kFailure;

                MDagPathArray paths;
                if ( MDagPath::getAllPathsTo ( object, paths ) != MStatus::kSuccess ) return MStatus::kFailure;

                int numPaths=paths.length();
                for ( int p=0; p<numPaths; p++ )
                    if ( p!=includedInstance )
                        selectionList.add ( paths[p] );
            }
        }

        return MStatus::kSuccess;
    }
Пример #5
0
void printMaterials(const MDagPath& dagPath) {
	MFnMesh fnMesh(dagPath);
	unsigned instanceNumber = dagPath.instanceNumber();
	MObjectArray sets;
	MObjectArray comps;
	fnMesh.getConnectedSetsAndMembers( instanceNumber, sets, comps, true );

	// Print Material Names
	for(unsigned int i = 0; i < sets.length(); ++i)
	{
		MFnDependencyNode fnDepSGNode(sets[i]);
		std::cout << fnDepSGNode.name() << std::endl;
	}
}
Пример #6
0
    // In order to correctly extract skinweights we first
    // need to go into bindpose. (and we need to remember the current
    // pose, to be able to undo it).
    //
    // I know: nearly no error-checking.
    void
    BindPoseTool::GoIntoBindPose()
    {
		MStatus status;
        std::cout << " Going into bindpose ";
        // == turn IK off
        // save current state
        undoInfo.ikSnap = MIkSystem::isGlobalSnap(&status);
        undoInfo.ikSolve = MIkSystem::isGlobalSolve();
        // turn it off
        MIkSystem::setGlobalSnap(false);
        MIkSystem::setGlobalSolve(false);

        // == put joints into bindPose
        for (MItDag dagIt(MItDag::kDepthFirst, MFn::kJoint);
             !dagIt.isDone();
             dagIt.next())
        {
            std::cout << ".";
            MDagPath jointPath;
            dagIt.getPath(jointPath);
            if (jointPath.isInstanced())
            { // we only work on the first instance of an instanced joint.
                if (jointPath.instanceNumber() != 0)
                    continue;
            }

            BindPoseUndoInformation::JointMatrixVector::value_type joint2transform;

            MFnIkJoint joint(jointPath.node());

            MTransformationMatrix currentTransform = joint.transformation(&status);

            joint2transform.first = jointPath.node();
            joint2transform.second = currentTransform;
            undoInfo.savedTransforms.push_back(joint2transform);

            MMatrix bindPoseMatrix = getBindPoseMatrix(joint);
            joint.set(bindPoseMatrix);
        }
        std::cout << std::endl;

        //cout << "bindPose end" << endl;
        // don't know, if this is really necessary, but MS xporttranslator
        // does it...
        syncMeshes();

	// remember the change
	inBindPose = true;
    }
IECore::ObjectPtr FromMayaTransformConverter::doConversion( const MDagPath &dagPath, IECore::ConstCompoundObjectPtr operands ) const
{
	MTransformationMatrix transform;

	if( m_spaceParameter->getNumericValue()==Local )
	{
		MFnTransform fnT( dagPath );
		transform = fnT.transformation();
	}
	else
	{
		unsigned instIndex = dagPath.instanceNumber();

		MObject dagNode = dagPath.node();
		MFnDependencyNode fnN( dagNode );

		MPlug plug = fnN.findPlug( "worldMatrix" );
		MPlug instPlug = plug.elementByLogicalIndex( instIndex );

		MObject matrix;
		instPlug.getValue( matrix );

		MFnMatrixData fnM( matrix );
		transform = fnM.transformation();

		if ( m_spaceParameter->getNumericValue() == Custom )
		{
			// multiply world transform by the inverse of the custom space matrix.
			transform = transform.asMatrix() * IECore::convert< MMatrix, Imath::M44f >( operands->member< IECore::M44fData >("customSpace", true)->readable().inverse() );
		}
	}

	if( m_zeroPivotsParameter->getTypedValue() )
	{
		transform.setScalePivot( MPoint( 0, 0, 0 ), MSpace::kTransform, true );
		transform.setRotatePivot( MPoint( 0, 0, 0 ), MSpace::kTransform, true );
	}

	if( m_eulerFilterParameter->getTypedValue() && m_lastRotationValid )
	{
		transform.rotateTo( transform.eulerRotation().closestSolution( m_lastRotation ) );
	}

	m_lastRotation = transform.eulerRotation();
	m_lastRotationValid = true;

	return new IECore::TransformationMatrixdData( IECore::convert<IECore::TransformationMatrixd, MTransformationMatrix>( transform ) );
}
    //------------------------------
    void MaterialExporter::exportConnectedMaterials ( SceneElement* sceneElement )
    {
        // If we have a external reference, we don't need to export the data here.
        if ( !sceneElement->getIsLocal() ) return;
        if ( !sceneElement->getIsExportNode () ) return;

        // Check if it is a mesh object and an export node
        if ( sceneElement->getType() == SceneElement::MESH )
        {
            MDagPath dagPath = sceneElement->getPath();

            // Attach a function set
            MStatus status;
            MFnMesh fnMesh ( dagPath.node(), &status );
            if ( status != MStatus::kSuccess ) return;

            // Find how many shaders are used by this instance of the mesh
            MObjectArray shaders;
            MIntArray shaderIndices;
            unsigned instanceNumber = dagPath.instanceNumber();
            fnMesh.getConnectedShaders ( instanceNumber, shaders, shaderIndices );

            // Find the polygons that correspond to each materials and export them
            uint realShaderCount = ( uint ) shaders.length();
            uint numShaders = ( uint ) std::max ( ( size_t ) 1, ( size_t ) shaders.length() );
            for ( uint shaderPosition = 0; shaderPosition < numShaders; ++shaderPosition )
            {
                if ( shaderPosition < realShaderCount )
                {
                    // Add shader-specific parameters (TexCoords sets).
                    // Add symbolic name for the material used on this polygon set.
                    MObject shadingEngine = shaders[shaderPosition];
                    exportMaterial ( shadingEngine );
                }
            }
        }

        // recursive call for all the child elements
        for ( uint i=0; i<sceneElement->getChildCount(); ++i )
        {
            SceneElement* childElement = sceneElement->getChild ( i );
            exportConnectedMaterials ( childElement );
        }
    }
Пример #9
0
MFnMesh* GDExporter::GetSelectedMesh(void)
{
	MSelectionList currSelection;
	MGlobal::getActiveSelectionList(currSelection);

	unsigned int selectionCount = currSelection.length();
	
	MFnMesh* exportingMesh = 0;

	for(unsigned int selectionIndex = 0; selectionIndex < selectionCount; ++selectionIndex )
	{
		MDagPath currPath;
		currSelection.getDagPath(selectionIndex, currPath);

		if( currPath.apiType() != MFn::kTransform )
			continue;

		MFnTransform currTransform(currPath);
		unsigned int childCount = currTransform.childCount();
		for(unsigned int childIndex = 0; childIndex < childCount; ++childIndex)
		{
			MObject childObject = currTransform.child(childIndex);
			if( childObject.apiType() == MFn::kMesh )
			{
				MFnDagNode dagNode;
				dagNode.setObject(childObject);
				MDagPath childPath;
				dagNode.getPath(childPath);
				
				MFnMesh* pChildMesh = new MFnMesh(childPath);
				
				if( pChildMesh->isIntermediateObject() )
					continue;
				
				bool bExportMesh = true;
				if( pChildMesh->isInstanced(false) )
					if( childPath.instanceNumber() != 0 )
						bExportMesh = false;

				if( bExportMesh )
				{
					if( exportingMesh != 0 )
					{
						delete exportingMesh;
						delete pChildMesh;
						MGlobal::displayError(MString("GDExporter - More than one mesh object selected."));
						return 0;
					}

					exportingMesh = pChildMesh;
				}
			}
		}
	}

	if( exportingMesh == 0 )
	{
		MGlobal::displayError(MString("GDExporter - No mesh objects currently selected."));
		return 0;
	}

	return exportingMesh;
}
MStatus findTexturesPerPolygon::doIt( const MArgList& )
//
//  Description:
//      Find the texture files that apply to the color of each polygon of
//      a selected shape if the shape has its polygons organized into sets.
//
{
    // Get the selection and choose the first path on the selection list.
    //
	MStatus status;
	MDagPath path;
	MObject cmp;
	MSelectionList slist;
	MGlobal::getActiveSelectionList(slist);
	slist.getDagPath(0, path, cmp);

	// Have to make the path include the shape below it so that
	// we can determine if the underlying shape node is instanced.
	// By default, dag paths only include transform nodes.
	//
	path.extendToShape();

	// If the shape is instanced then we need to determine which
	// instance this path refers to.
	//
	int instanceNum = 0;
	if (path.isInstanced())
		instanceNum = path.instanceNumber();

    // Get a list of all sets pertaining to the selected shape and the
    // members of those sets.
    //
	MFnMesh fnMesh(path);
	MObjectArray sets;
	MObjectArray comps;
	if (!fnMesh.getConnectedSetsAndMembers(instanceNum, sets, comps, true))
		cerr << "ERROR: MFnMesh::getConnectedSetsAndMembers\n";

	// Loop through all the sets.  If the set is a polygonal set, find the
    // shader attached to the and print out the texture file name for the
    // set along with the polygons in the set.
	//
	for ( unsigned i=0; i<sets.length(); i++ ) {
		MObject set = sets[i];
		MObject comp = comps[i];

		MFnSet fnSet( set, &status );
		if (status == MS::kFailure) {
            cerr << "ERROR: MFnSet::MFnSet\n";
            continue;
        }

        // Make sure the set is a polygonal set.  If not, continue.
		MItMeshPolygon piter(path, comp, &status);
		if ((status == MS::kFailure) || comp.isNull())
            continue;

		// Find the texture that is applied to this set.  First, get the
		// shading node connected to the set.  Then, if there is an input
		// attribute called "color", search upstream from it for a texture
		// file node.
        //
		MObject shaderNode = findShader(set);
		if (shaderNode == MObject::kNullObj)
			continue;

		MPlug colorPlug = MFnDependencyNode(shaderNode).findPlug("color", &status);
		if (status == MS::kFailure)
			continue;

		MItDependencyGraph dgIt(colorPlug, MFn::kFileTexture,
						   MItDependencyGraph::kUpstream, 
						   MItDependencyGraph::kBreadthFirst,
						   MItDependencyGraph::kNodeLevel, 
						   &status);

		if (status == MS::kFailure)
			continue;
		
		dgIt.disablePruningOnFilter();

        // If no texture file node was found, just continue.
        //
		if (dgIt.isDone())
			continue;
		  
        // Print out the texture node name and texture file that it references.
        //
		MObject textureNode = dgIt.thisNode();
        MPlug filenamePlug = MFnDependencyNode(textureNode).findPlug("fileTextureName");
        MString textureName;
        filenamePlug.getValue(textureName);
		cerr << "Set: " << fnSet.name() << endl;
        cerr << "Texture Node Name: " << MFnDependencyNode(textureNode).name() << endl;
		cerr << "Texture File Name: " << textureName.asChar() << endl;
        
        // Print out the set of polygons that are contained in the current set.
        //
		for ( ; !piter.isDone(); piter.next() )
			cerr << "    poly component: " << piter.index() << endl;
	}

	return MS::kSuccess;
}
    // --------------------------------------------------------------------
    bool SceneGraph::getIsExportNode ( 
        const MDagPath& dagPath, 
        bool& isForced,
        bool& isVisible )
    {
        // Does this dagPath already exist? If so, only recurse if FollowInstancedChildren() is set.
        MFnDagNode dagFn ( dagPath );
        String dagNodeName = dagFn.name().asChar();

        bool isSceneRoot = dagPath.length() == 0;

        // Ignore default and intermediate nodes (history items)
        bool isIntermediateObject = dagFn.isIntermediateObject();
        if ( ( dagFn.isDefaultNode() && !isSceneRoot ) || isIntermediateObject )
        {
            return false;
        }

        MString nodeName = dagPath.partialPathName();
        if ( nodeName == MString ( NIMA_INTERNAL_PHYSIKS ) )
        {
            // Skip this node, which is only used
            // by Nima as a work-around for a Maya bug.
            return false;
        }

        // If we are not already forcing this node, its children
        // check whether we should be forcing it (skinning of hidden joints).
        isForced = isForcedNode ( dagPath );
        DagHelper::getPlugValue ( dagPath.node(), ATTR_VISIBILITY, isVisible );
        bool isInstanced = dagPath.isInstanced();
        uint instanceNumber = dagPath.instanceNumber();

        if ( !isForced )
        {
            // Check for visibility
            if ( !ExportOptions::exportInvisibleNodes() && !isVisible )
            {
                // Check if the visibility of the element is animated.
                AnimationSampleCache* animationCache = mDocumentExporter->getAnimationCache();
                if ( !AnimationHelper::isAnimated ( animationCache, dagPath.node(), ATTR_VISIBILITY ) )
                {
                    return false;
                }
            }
            else if ( !isVisible && !ExportOptions::exportDefaultCameras() )
            {
                // Check for the default camera transform names.
                if ( nodeName == CAMERA_PERSP || nodeName == CAMERA_TOP || nodeName == CAMERA_SIDE || nodeName == CAMERA_FRONT ||
                     nodeName == CAMERA_PERSP_SHAPE || nodeName == CAMERA_TOP_SHAPE || nodeName == CAMERA_SIDE_SHAPE || nodeName == CAMERA_FRONT_SHAPE )
                    return false;
            }
        }

        isForced &= !isVisible;
        if ( !isForced )
        {
            // We don't want to process manipulators
            if ( dagPath.hasFn ( MFn::kManipulator ) || dagPath.hasFn ( MFn::kViewManip ) ) return false;

            // Check for constraints which are not exported
            //if ( !ExportOptions::exportConstraints() && dagPath.hasFn ( MFn::kConstraint ) ) return false;
            if ( dagPath.hasFn ( MFn::kConstraint ) ) return false;

            // Check set membership exclusion/inclusion
            if ( SetHelper::isExcluded ( dagPath ) ) return false;
        }

        return true;
    }
Пример #12
0
bool getObjectShadingGroups(const MDagPath& shapeObjectDP, MIntArray& perFaceAssignments, MObjectArray& shadingGroups, bool needsPerFaceInfo=true)
{
    // if obj is a light, simply return the mobject
    if (shapeObjectDP.node().hasFn(MFn::kLight))
    {
        perFaceAssignments.clear();
        shadingGroups.clear();
        shadingGroups.append(shapeObjectDP.node());
        return true;
    }

    if (shapeObjectDP.node().hasFn(MFn::kMesh))
    {
        // Find the Shading Engines Connected to the SourceNode
        MFnMesh meshFn(shapeObjectDP.node());

        perFaceAssignments.clear();
        shadingGroups.clear();
        MObjectArray comps;

        // this one seems to be extremly much faster if we need no per face informations.
        // e.g. for a sphere with 90000 faces, the non per face method needs 0.05 sec. whereas the
        // method with per face info needs about 20 sec.
        if (!needsPerFaceInfo)
        {
            meshFn.getConnectedSetsAndMembers(shapeObjectDP.instanceNumber(), shadingGroups, comps, true);
            return true;
        }

        meshFn.getConnectedShaders(shapeObjectDP.instanceNumber(), shadingGroups, perFaceAssignments);

        if (!meshFn.findPlug("displaySmoothMesh").asBool())
            return true;

        MIntArray indices;
        indices = perFaceAssignments;

        int subdivs = 0;
        int multiplier = 0;

        if (meshFn.findPlug("displaySmoothMesh").asBool())
        {
            MMeshSmoothOptions options;
            MStatus status = meshFn.getSmoothMeshDisplayOptions(options);
            if (status)
            {
                if (!meshFn.findPlug("useSmoothPreviewForRender", false, &status).asBool())
                {
                    int smoothLevel = meshFn.findPlug("renderSmoothLevel", false, &status).asInt();
                    options.setDivisions(smoothLevel);
                }

                subdivs = options.divisions();
                if (subdivs > 0)
                    multiplier = static_cast<int> (pow(4.0f, (subdivs - 1)));
            }
        }

        if (multiplier > 0)
            perFaceAssignments.clear();

        for (unsigned int i = 0; i < indices.length(); i++)
        {
            int subdivisions = multiplier * meshFn.polygonVertexCount(i);
            int index = 0 > indices[i] ? 0 : indices[i]; // non assigned has -1, but we want 0
            perFaceAssignments.append(index);

            // simply replicate the index for all subdiv faces
            for (int k = 0; k < subdivisions - 1; k++)
                perFaceAssignments.append(index);
        }
        return true;
    }

    if (shapeObjectDP.node().hasFn(MFn::kNurbsSurface)||shapeObjectDP.hasFn(MFn::kParticle)||shapeObjectDP.hasFn(MFn::kNParticle))
    {
        MObject instObjGroupsAttr;
        if (shapeObjectDP.hasFn(MFn::kNurbsSurface))
        {
            MFnNurbsSurface fnNurbs(shapeObjectDP.node());
            instObjGroupsAttr = fnNurbs.attribute("instObjGroups");
        }
        if (shapeObjectDP.hasFn(MFn::kParticle)||shapeObjectDP.hasFn(MFn::kNParticle))
        {
            MFnParticleSystem fnPart(shapeObjectDP.node());
            instObjGroupsAttr = fnPart.attribute("instObjGroups");
        }
        MPlug instPlug(shapeObjectDP.node(), instObjGroupsAttr);

        // Get the instance that our node is referring to;
        // In other words get the Plug for instObjGroups[intanceNumber];
        MPlug instPlugElem = instPlug.elementByLogicalIndex(shapeObjectDP.instanceNumber());

        // Find the ShadingGroup plugs that we are connected to as Source
        MPlugArray SGPlugArray;
        instPlugElem.connectedTo(SGPlugArray, false, true);

        perFaceAssignments.clear();
        shadingGroups.clear();

        // Loop through each ShadingGroup Plug
        for (unsigned int i=0; i < SGPlugArray.length(); ++i)
        {
            shadingGroups.append(SGPlugArray[i].node());
            return true;
        }
    }
    return false;
}
Пример #13
0
void extractPolygons(Model* model) {

	MStatus stat;
	MItDag dagIter(MItDag::kBreadthFirst, MFn::kInvalid);

	for (; !dagIter.isDone(); dagIter.next()) {
		MDagPath dagPath;
		stat = dagIter.getPath(dagPath);
		if (!stat) { continue; };

		MFnDagNode dagNode(dagPath, &stat);

		if (dagNode.isIntermediateObject()) continue;
		if (!dagPath.hasFn( MFn::kMesh )) continue;
		if (dagPath.hasFn( MFn::kTransform)) continue;
		if (!dagPath.isVisible()) continue;

		MFnMesh fnMesh(dagPath);

		MStringArray  UVSets;
		stat = fnMesh.getUVSetNames( UVSets );

		// Get all UVs for the first UV set.
		MFloatArray   u, v;
		fnMesh.getUVs(u, v, &UVSets[0]);


		MPointArray vertexList;
		fnMesh.getPoints(vertexList, MSpace::kObject);

		MFloatVectorArray  meshNormals;
		fnMesh.getNormals(meshNormals);


		unsigned instanceNumber = dagPath.instanceNumber();
		MObjectArray sets;
		MObjectArray comps;
		fnMesh.getConnectedSetsAndMembers( instanceNumber, sets, comps, true );

		//printMaterials(dagPath);

		unsigned int comlength = comps.length();

		for (unsigned int compi = 0; compi < comlength; compi++) {

			SubMesh submesh;

			MItMeshPolygon itPolygon(dagPath, comps[compi]);

			unsigned int polyCount = 0;
			for (; !itPolygon.isDone(); itPolygon.next()) {
				polyCount++;
				MIntArray                           polygonVertices;
				itPolygon.getVertices(polygonVertices);

				int count;
				itPolygon.numTriangles(count);

				for (; count > -1; count--) {
					MPointArray                     nonTweaked;
					MIntArray                       triangleVertices;
					MIntArray                       localIndex;

					MStatus  status;
					status = itPolygon.getTriangle(count, nonTweaked, triangleVertices, MSpace::kObject);

					if (status == MS::kSuccess) {

						VertexDefinition vertex1;
						VertexDefinition vertex2;
						VertexDefinition vertex3;

						{ // vertices

							int vertexCount = vertexList.length();

							{
								int vertexIndex0 = triangleVertices[0];
								MPoint point0 = vertexList[vertexIndex0];

								vertex1.vertex.x = (float)point0.x;
								vertex1.vertex.y = (float)point0.y;
								vertex1.vertex.z = (float)point0.z;
							}

							{
								int vertexIndex0 = triangleVertices[1];
								MPoint point0 = vertexList[vertexIndex0];

								vertex2.vertex.x = (float)point0.x;
								vertex2.vertex.y = (float)point0.y;
								vertex2.vertex.z = (float)point0.z;
							}

							{
								int vertexIndex0 = triangleVertices[2];
								MPoint point0 = vertexList[vertexIndex0];

								vertex3.vertex.x = (float)point0.x;
								vertex3.vertex.y = (float)point0.y;
								vertex3.vertex.z = (float)point0.z;
							}

						}

						{ // normals

							// Get face-relative vertex indices for this triangle
							localIndex = GetLocalIndex(polygonVertices, triangleVertices);

							{
								int index0 = itPolygon.normalIndex(localIndex[0]);
								MPoint point0 = meshNormals[index0];

								vertex1.normal.x = (float)point0.x;
								vertex1.normal.y = (float)point0.y;
								vertex1.normal.z = (float)point0.z;
							}

							{
								int index0 = itPolygon.normalIndex(localIndex[1]);
								MPoint point0 = meshNormals[index0];

								vertex2.normal.x = (float)point0.x;
								vertex2.normal.y = (float)point0.y;
								vertex2.normal.z = (float)point0.z;
							}

							{
								int index0 = itPolygon.normalIndex(localIndex[2]);
								MPoint point0 = meshNormals[index0];

								vertex3.normal.x = (float)point0.x;
								vertex3.normal.y = (float)point0.y;
								vertex3.normal.z = (float)point0.z;
							}
						}

						{ // uvs

							int uvID[3];

							MStatus uvFetchStatus;
							for (unsigned int vtxInPolygon = 0; vtxInPolygon < 3; vtxInPolygon++) {
								uvFetchStatus = itPolygon.getUVIndex(localIndex[vtxInPolygon], uvID[vtxInPolygon]);
							}

							if (uvFetchStatus == MStatus::kSuccess) {

								{
									int index0 = uvID[0];
									float uvu = u[index0];
									float uvv = v[index0];

									vertex1.uv.x = uvu;
									vertex1.uv.y = 1.0f - uvv;
								}

								{
									int index0 = uvID[1];
									float uvu = u[index0];
									float uvv = v[index0];

									vertex2.uv.x = uvu;
									vertex2.uv.y = 1.0f - uvv;
								}

								{
									int index0 = uvID[2];
									float uvu = u[index0];
									float uvv = v[index0];

									vertex3.uv.x = uvu;
									vertex3.uv.y = 1.0f - uvv; // directx
								}
							}
						}

						submesh.addVertex(vertex1);
						submesh.addVertex(vertex2);
						submesh.addVertex(vertex3);
					}
				}
			}

			{
				Material material;

				{
					MObjectArray shaders;
					MIntArray indices;
					fnMesh.getConnectedShaders(0, shaders, indices);
					unsigned int shaderCount = shaders.length();

					MPlugArray connections;
					MFnDependencyNode shaderGroup(shaders[compi]);
					MPlug shaderPlug = shaderGroup.findPlug("surfaceShader");
					shaderPlug.connectedTo(connections, true, false);

					for(unsigned int u = 0; u < connections.length(); u++) {
						if(connections[u].node().hasFn(MFn::kLambert)) {

							MFnLambertShader lambertShader(connections[u].node());
							MPlugArray plugs;
							lambertShader.findPlug("color").connectedTo(plugs, true, false);

							for (unsigned int p = 0; p < plugs.length(); p++) {
								MPlug object = plugs[p];
								if (!object.isNull()) {
									MObject node = object.node();
									if (node.hasFn(MFn::kFileTexture)) {
										MFnDependencyNode* diffuseMapNode = new MFnDependencyNode(node);

										MPlug filenamePlug = diffuseMapNode->findPlug ("fileTextureName");
										MString mayaFileName;
										filenamePlug.getValue (mayaFileName);
										std::string diffuseMapFileName = mayaFileName.asChar();
										std::string diffuseMapAssetPath = extractAssetPath(diffuseMapFileName);
										material.addTexture("ColorMap", diffuseMapAssetPath);
									}
								} 
							}

							MColor color = lambertShader.color();
							MString materialNameRaw = lambertShader.name();
							std::string materialName = materialNameRaw.asChar();
							material.setName(materialName);

							Vector4MaterialParameter* diffuseColorParameter = new Vector4MaterialParameter("DiffuseColor");
							diffuseColorParameter->value.x = color.r;
							diffuseColorParameter->value.y = color.g;
							diffuseColorParameter->value.z = color.b;
							diffuseColorParameter->value.w = color.a;

							material.addParameter(diffuseColorParameter);
						}
					}
				}

				{
					if (material.hasTextures()) {
						material.setEffect("shaders/deferred_render_colormap_normal_depth.cg");
					}
					else {
						material.setEffect("shaders/deferred_render_color_normal_depth.cg");
					}
				}


				{
					FloatMaterialParameter* specularPowerParameter = new FloatMaterialParameter("SpecularPower");
					specularPowerParameter->value = 1.0;
					material.addParameter(specularPowerParameter);
				}

				{
					FloatMaterialParameter* specularIntensityParameter = new FloatMaterialParameter("SpecularIntensity");
					specularIntensityParameter->value = 1.0f;
					material.addParameter(specularIntensityParameter);
				}

				{
					FloatMaterialParameter* diffusePowerParameter = new FloatMaterialParameter("DiffusePower");
					diffusePowerParameter->value = 1.0f;
					material.addParameter(diffusePowerParameter);
				}

				submesh.setMaterial(material);
			}

			model->addSubMesh(submesh);
		}
	}
}
Пример #14
0
MStatus CVstAimCmd::redoIt()
{
	MStatus mStatus;

	if ( !mStatus )
	{
		setResult( MString( "Cannot parse command line" ) + mStatus.errorString() );
		return MS::kFailure;
	}

	if ( m_mArgDatabase->isFlagSet( kHelp ) )
	{
		PrintHelp();
	}
	else
	{
		// See if there are two object specified

		MDagPath mDagPath;
		MSelectionList optSelectionList;

		// Validate specified items to whole dag nodes
		{
			MSelectionList tmpSelectionList;
			m_mArgDatabase->getObjects( tmpSelectionList );
			for ( MItSelectionList sIt( tmpSelectionList, MFn::kDagNode ); !sIt.isDone(); sIt.next() )
			{
				if ( sIt.getDagPath( mDagPath ) )
				{
					optSelectionList.add( mDagPath, MObject::kNullObj, true );
				}
			}
		}

		if ( m_mArgDatabase->isFlagSet( "create" ) || optSelectionList.length() >= 2 && m_mArgDatabase->numberOfFlagsUsed() == 0 )
		{
			// Error if there aren't at least two
			if ( optSelectionList.length() < 2 )
			{
				displayError( GetName() + " needs at least two objects specified or selected when -create is used" );
				return MS::kFailure;
			}

			// Get name command line arg
			MString optName;
			if ( m_mArgDatabase->isFlagSet( "name" ) )
			{
				m_mArgDatabase->getFlagArgument( "name", 0, optName );
			}

			m_undoable = true;
			m_mDagModifier = new MDagModifier;

			MObject vstAimObj( m_mDagModifier->MDGModifier::createNode( GetName() ) );
			if ( m_mDagModifier->doIt() != MS::kSuccess )
			{
				displayError( MString( "Couldn't create " ) + GetName() + " node" );
				m_mDagModifier->undoIt();
				delete m_mDagModifier;
				m_mDagModifier = NULL;
				m_undoable = false;

				return MS::kFailure;
			}

			m_mDagModifier->renameNode( vstAimObj, optName.length() ? optName : GetName() );
			if ( m_mDagModifier->doIt() != MS::kSuccess )
			{
				if ( optName.length() )
				{
					displayWarning( MString( "Couldn't rename newly created vstNode \"" ) + optName + "\"" );
				}
			}

			// Set options on the newly create vstAim node

			MFnDependencyNode vstAimFn( vstAimObj );

			MPlug sP;
			MPlug dP;

			if ( m_mArgDatabase->isFlagSet( kAim ) )
			{
				MVector aim;
				m_mArgDatabase->getFlagArgument( kAim, 0, aim.x );
				m_mArgDatabase->getFlagArgument( kAim, 1, aim.y );
				m_mArgDatabase->getFlagArgument( kAim, 2, aim.z );

				sP = vstAimFn.findPlug( "aimX" );
				sP.setValue( aim.x );

				sP = vstAimFn.findPlug( "aimY" );
				sP.setValue( aim.y );

				sP = vstAimFn.findPlug( "aimZ" );
				sP.setValue( aim.z );
			}

			if ( m_mArgDatabase->isFlagSet( kUp ) )
			{
				MVector up;
				m_mArgDatabase->getFlagArgument( kUp, 0, up.x );
				m_mArgDatabase->getFlagArgument( kUp, 1, up.y );
				m_mArgDatabase->getFlagArgument( kUp, 2, up.z );

				sP = vstAimFn.findPlug( "upX" );
				sP.setValue( up.x );

				sP = vstAimFn.findPlug( "upY" );
				sP.setValue( up.y );

				sP = vstAimFn.findPlug( "upZ" );
				sP.setValue( up.z );
			}

			// Now connect up the newly created vstAim node

			MDagPath toAim;
			optSelectionList.getDagPath( 1, toAim );
			const MFnDagNode toAimFn( toAim );

			if ( toAim.hasFn( MFn::kJoint ) )
			{
				MPlug joP( toAimFn.findPlug( "jointOrient" ) );
				if ( !joP.isNull() )
				{
					MAngle jox, joy, joz;
					joP.child( 0 ).getValue( jox );
					joP.child( 1 ).getValue( joy );
					joP.child( 2 ).getValue( joz );
					if ( abs( jox.value() ) > FLT_EPSILON || abs( joy.value() ) > FLT_EPSILON || abs( joz.value() ) > FLT_EPSILON )
					{
						mwarn << "Joint orient on node being constrained is non-zero ( " << jox.asDegrees() << " " << joy.asDegrees() << " " << joz.asDegrees() << " ), setting to 0" << std::endl;
						joP.child( 0 ).setValue( MAngle( 0.0 ) );
						joP.child( 1 ).setValue( MAngle( 0.0 ) );
						joP.child( 2 ).setValue( MAngle( 0.0 ) );
					}
				}
			}

			if ( toAim.hasFn( MFn::kTransform ) )
			{
				MPlug mP( toAimFn.findPlug( "rotateAxis" ) );
				if ( !mP.isNull() )
				{
					MAngle rx, ry, rz;
					mP.child( 0 ).getValue( rx );
					mP.child( 1 ).getValue( ry );
					mP.child( 2 ).getValue( rz );
					if ( abs( rx.value() ) > FLT_EPSILON || abs( ry.value() ) > FLT_EPSILON || abs( rz.value() ) > FLT_EPSILON )
					{
						mwarn << "Rotate Axis on node being constrained is non-zero ( " << rx.asDegrees() << " " << ry.asDegrees() << " " << rz.asDegrees() << " ), setting to 0" << std::endl;
						mP.child( 0 ).setValue( MAngle( 0.0 ) );
						mP.child( 1 ).setValue( MAngle( 0.0 ) );
						mP.child( 2 ).setValue( MAngle( 0.0 ) );
					}
				}
			}

			MDagPath aimAt;
			optSelectionList.getDagPath( 0, aimAt );
			const MFnDagNode aimAtFn( aimAt );

			// toAim.rotateOrder -> vstAim.rotateOrder
			sP = toAimFn.findPlug( "rotateOrder" );
			dP = vstAimFn.findPlug( "rotateOrder" );
			m_mDagModifier->connect( sP, dP );

			// toAim.translate -> vstAim.translate
			sP = toAimFn.findPlug( "translate" );
			dP = vstAimFn.findPlug( "translate" );
			m_mDagModifier->connect( sP, dP );

			// toAim.parentMatrix[ instance ] -> vstAim.parentSpace
			sP = toAimFn.findPlug( "parentMatrix" );
			sP = sP.elementByLogicalIndex( toAim.instanceNumber() );
			dP = vstAimFn.findPlug( "parentSpace" );
			m_mDagModifier->connect( sP, dP );

			// aimAt.worldMatrix[ instance ] -> vstAim.aimSpace
			sP = aimAtFn.findPlug( "worldMatrix" );
			sP = sP.elementByLogicalIndex( aimAt.instanceNumber() );
			dP = vstAimFn.findPlug( "aimSpace" );
			m_mDagModifier->connect( sP, dP );

			// vstAim.rotation -> toAim.rotation
			// These have to be connected individually because Maya plays stupid tricks
			// with rotateOrder if they aren't
			sP = vstAimFn.findPlug( "rotateX" );
			dP = toAimFn.findPlug( "rotateX" );
			m_mDagModifier->connect( sP, dP );

			sP = vstAimFn.findPlug( "rotateY" );
			dP = toAimFn.findPlug( "rotateY" );
			m_mDagModifier->connect( sP, dP );

			sP = vstAimFn.findPlug( "rotateZ" );
			dP = toAimFn.findPlug( "rotateZ" );
			m_mDagModifier->connect( sP, dP );

			if ( m_mDagModifier->doIt() != MS::kSuccess )
			{
				displayWarning( MString( GetName() ) + ": Couldn't connect everything when creating" );
			}

			// Save the current selection just in case we want to undo stuff
			MGlobal::getActiveSelectionList( m_mSelectionList );

			MGlobal::select( vstAimObj, MGlobal::kReplaceList );
			setResult( vstAimFn.name() );
		}
		else if ( m_mArgDatabase->isFlagSet( "select" ) )
		{
			MSelectionList mSelectionList;
			MDagPath mDagPath;

			for ( MItDag dagIt; !dagIt.isDone(); dagIt.next() )
			{
				if ( MFnDependencyNode( dagIt.item() ).typeName() == GetName() )
				{
					dagIt.getPath( mDagPath );
					mSelectionList.add( mDagPath, MObject::kNullObj, true );
				}
			}

			if ( mSelectionList.length() )
			{
				m_undoable = true;
				// Save the current selection just in case we want to undo stuff
				MGlobal::getActiveSelectionList( m_mSelectionList );
				MGlobal::setActiveSelectionList( mSelectionList, MGlobal::kReplaceList );
			}
		}
		else
		{
			displayError( GetName() + ": No valid operation specified via command line arguments\n" );
		}
	}

	return MS::kSuccess;
}
// Get shading engine
//
void CScriptedShapeTranslator::GetShapeInstanceShader(MDagPath& dagPath, MFnDependencyNode &shadingEngineNode)
{
   // Get instance shadingEngine
   shadingEngineNode.setObject(MObject::kNullObj);
   
   // First try the usual way
   MPlug shadingGroupPlug = GetNodeShadingGroup(dagPath.node(), (dagPath.isInstanced() ? dagPath.instanceNumber() : 0));
   if (!shadingGroupPlug.isNull())
   {
      shadingEngineNode.setObject(shadingGroupPlug.node());
      return;
   }
   
   char buffer[64];
   
   // Check connection from any shadingEngine on shape
   MStringArray connections;
   MGlobal::executeCommand("listConnections -s 1 -d 0 -c 1 -type shadingEngine "+dagPath.fullPathName(), connections);
   
   MSelectionList sl;
   
   if (connections.length() == 0)
   {
      // Check for direct surface shader connection
      MGlobal::executeCommand("listConnections -s 1 -d 0 -c 1 "+dagPath.fullPathName(), connections);
      
      for (unsigned int cidx=0; cidx<connections.length(); cidx+=2)
      {
         MString srcNode = connections[cidx+1];
         // Get node classification, if can find arnold/shader/surface -> got it
         MStringArray rv;
         MGlobal::executeCommand("getClassification `nodeType "+srcNode+"`", rv);
         if (rv.length() > 0 && rv[0].indexW("arnold/shader/surface") != -1)
         {
            connections.clear();
            
            MGlobal::executeCommand("listConnections -s 0 -d 1 -c 1 -type shadingEngine "+srcNode, connections);
            
            if (connections.length() == 2)
            {
               sl.add(connections[1]);
            }
            
            break;
         }
      }
   }
   else if (connections.length() == 2)
   {
      // Single connection, use same shader for all instances
      sl.add(connections[1]);
   }
   else if (connections.length() > 2)
   {
      // Many connections, expects the destination plug in shape to be an array
      // Use instance number as logical index, if this fails, use first shadingEngine in list
      
      bool found = false;
      
      sprintf(buffer, "[%d]", dagPath.instanceNumber());
      MString iidx = buffer;
      
      for (unsigned int cidx = 0; cidx < connections.length(); cidx += 2)
      {
         MString conn = connections[cidx];
         
         if (conn.length() < iidx.length())
         {
            continue;
         }
         
         if (conn.substring(conn.length() - iidx.length(), conn.length() - 1) != iidx)
         {
            continue;
         }
         
         sl.add(connections[cidx+1]);
         
         found = true;
         
         break;
      }
      
      if (!found)
      {
         MGlobal::displayWarning("[mtoaScriptedTranslators] Instance shader plug not found, use first found shadingEngine \"" + connections[1] + "\"");
         sl.add(connections[1]);
      }
   }
   
   if (sl.length() == 1)
   {
      MObject shadingEngineObj;
      
      if (sl.getDependNode(0, shadingEngineObj) == MS::kSuccess && shadingEngineObj.apiType() == MFn::kShadingEngine)
      {
         shadingEngineNode.setObject(shadingEngineObj);
      }
      else
      {
         if (shadingEngineObj != MObject::kNullObj)
         {
            MFnDependencyNode dn(shadingEngineObj);
            MGlobal::displayWarning("[mtoaScriptedTranslators] Not a shading engine \"" + dn.name() + "\"");
         }
      }
   }
}
Пример #16
0
MStatus CXRayObjectExport::ExportPart(CEditableObject* O, MDagPath& mdagPath, MObject&  mComponent)
{
	MStatus stat = MS::kSuccess;
	MSpace::Space space = MSpace::kWorld;

	MFnMesh fnMesh( mdagPath, &stat );
	if ( MS::kSuccess != stat) {
		fprintf(stderr,"Failure in MFnMesh initialization.\n");
		return MS::kFailure;
	}

	MString mdagPathNodeName = fnMesh.name();

	MFnDagNode dagNode1(mdagPath);
	u32 pc = dagNode1.parentCount();
	for(u32 ip=0;ip<pc;++ip)
	{
		MObject object_parent = dagNode1.parent(ip, &stat);
		if(object_parent.hasFn(MFn::kTransform))
		{
			MFnTransform parent_transform(object_parent,&stat);
	
			if ( MS::kSuccess == stat) 
			{
				mdagPathNodeName = parent_transform.name();
				break;
			}
		}
	}

	MItMeshPolygon meshPoly( mdagPath, mComponent, &stat );
	if ( MS::kSuccess != stat) {
		fprintf(stderr,"Failure in MItMeshPolygon initialization.\n");
		return MS::kFailure;
	}

	MItMeshVertex vtxIter( mdagPath, mComponent, &stat );
	if ( MS::kSuccess != stat) {
		fprintf(stderr,"Failure in MItMeshVertex initialization.\n");
		return MS::kFailure;
	}

	// If the shape is instanced then we need to determine which
	// instance this path refers to.
	//
	int instanceNum = 0;
	if (mdagPath.isInstanced())
		instanceNum = mdagPath.instanceNumber();

	// Get a list of all shaders attached to this mesh
	MObjectArray rgShaders;
	MIntArray texMap;
	MStatus status;
	status = fnMesh.getConnectedShaders (instanceNum, rgShaders, texMap);
	if (status == MStatus::kFailure)
	{
		Log("! Unable to load shaders for mesh");
		return (MStatus::kFailure);
	}

	XRShaderDataVec xr_data;
	{
		for ( int i=0; i<(int)rgShaders.length(); i++ ) {
			MObject shader = rgShaders[i];

			xr_data.push_back(SXRShaderData());
			SXRShaderData& D = xr_data.back();

			status = parseShader(shader, D);
			if (status == MStatus::kFailure) {
				status.perror ("Unable to retrieve filename of texture");
				continue;
			}
		}
	}

	CEditableMesh* MESH = new CEditableMesh(O);
	MESH->SetName(mdagPathNodeName.asChar());
	O->AppendMesh(MESH);

	int objectIdx, length;

	// Find i such that objectGroupsTablePtr[i] corresponds to the
	// object node pointed to by mdagPath
	length = objectNodeNamesArray.length();
	{
		for( int i=0; i<length; i++ ) {
			if( objectNodeNamesArray[i] == mdagPathNodeName ) {
				objectIdx = i;
				break;
			}
		}
	}
	// Reserve uv table
	{
		VMapVec& _vmaps	= MESH->m_VMaps;
		_vmaps.resize	(1);
		st_VMap*& VM	= _vmaps.back();
		VM				= new st_VMap("Texture",vmtUV,false);
	}

	// write faces
	{
		using FaceVec = xr_vector<st_Face>;
		using FaceIt = FaceVec::iterator;

		VMapVec& _vmaps			= MESH->m_VMaps;
		SurfFaces& _surf_faces	= MESH->m_SurfFaces;
		VMRefsVec& _vmrefs		= MESH->m_VMRefs;
		
		// temp variables
		FvectorVec	_points;
		FaceVec _faces;
		U32Vec _sgs;

		int f_cnt				= fnMesh.numPolygons();

		_sgs.reserve	(f_cnt);
		_faces.reserve	(f_cnt);
		_vmrefs.reserve	(f_cnt*3);

//		int lastSmoothingGroup = INITIALIZE_SMOOTHING;
		MPointArray rgpt;
		MIntArray rgint;

		PtLookupMap ptMap;
		CSurface* surf	= 0;
		for ( ; !meshPoly.isDone(); meshPoly.next()){
			// Write out the smoothing group that this polygon belongs to
			// We only write out the smoothing group if it is different
			// from the last polygon.
			//
			int compIdx	= meshPoly.index();
			int smoothingGroup = polySmoothingGroups[ compIdx ];
			// for each polygon, first setup the reverse mapping
			// between object-relative vertex indices and face-relative
			// vertex indices
			ptMap.clear();
			for (int i=0; i<(int)meshPoly.polygonVertexCount(); i++)
				ptMap.insert (PtLookupMap::value_type(meshPoly.vertexIndex(i), i) );

			// verify polygon zero area
			if (meshPoly.zeroArea()){
				status = MS::kFailure;
				Log("! polygon have zero area:",meshPoly.index());
				return status;
			}

			// verify polygon zero UV area
/*			if (meshPoly.zeroUVArea()){
				status = MS::kFailure;
				Log("! polygon have zero UV area:",meshPoly.index());
				return status;
			}
*/
			// verify polygon has UV information
			if (!meshPoly.hasUVs (&status)) {
				status = MS::kFailure;
				Log("! polygon is missing UV information:",meshPoly.index());
				return status;
			}

			int cTri;
			// now iterate through each triangle on this polygon and create a triangle object in our list
			status = meshPoly.numTriangles (cTri);	
			if (!status) {
				Log("! can't getting triangle count");
				return status;
			}

			for (int i=0; i < cTri; i++) {

				// for each triangle, first get the triangle data
				rgpt.clear();//triangle vertices
				rgint.clear();//triangle vertex indices 

				// triangles that come from object are retrieved in world space
				status = meshPoly.getTriangle (i, rgpt, rgint, MSpace::kWorld);

				if (!status) {
					Log("! can't getting triangle for mesh poly");
					return status;
				}

				if ((rgpt.length() != 3) || (rgint.length() != 3)) {
					Msg("! 3 points not returned for triangle");
					return MS::kFailure;
				}

				// Write out vertex/uv index information
				//
				R_ASSERT2(fnMesh.numUVs()>0,"Can't find uvmaps.");
				_faces.push_back(st_Face());
				_sgs.push_back(smoothingGroup);
				//set_smooth
				set_smoth_flags( _sgs.back(), rgint );

				st_Face& f_it		= _faces.back();
				for ( int vtx=0; vtx<3; vtx++ ) {
					// get face-relative vertex
					PtLookupMap::iterator mapIt;

					int vtLocal, vtUV;
					int vt = rgint[vtx];
					mapIt = ptMap.find(vt);
					Fvector2 uv;
					if (mapIt == ptMap.end()){
						Msg("! Can't find local index.");
						return MS::kFailure;
					}
					vtLocal = (*mapIt).second;

					status = meshPoly.getUVIndex (vtLocal, vtUV, uv.x, uv.y); 
					if (!status) {
						Msg("! error getting UV Index for local vertex '%d' and object vertex '%d'",vtLocal,vt);
						return status;
					}

					// flip v-part 
					uv.y=1.f-uv.y;

					f_it.pv[2-vtx].pindex	= AppendVertex(_points,rgpt[vtx]);
					f_it.pv[2-vtx].vmref	= _vmrefs.size();
					_vmrefs.push_back		(st_VMapPtLst());
					st_VMapPtLst& vm_lst	= _vmrefs.back();
					vm_lst.count			= 1;
					vm_lst.pts				= xr_alloc<st_VMapPt>(vm_lst.count);
					vm_lst.pts[0].vmap_index= 0;
					vm_lst.pts[0].index 	= AppendUV(_vmaps.back(),uv);
				}
				// out face material
				int iTexture	= texMap[meshPoly.index()];
				if (iTexture<0)
					xrDebug::Fatal(DEBUG_INFO,"Can't find material for polygon: %d",meshPoly.index());
				SXRShaderData& D= xr_data[iTexture];

				int compIdx = meshPoly.index();
				surf		= MESH->Parent()->CreateSurface(getMaterialName(mdagPath, compIdx, objectIdx),D);
				if (!surf)	return MStatus::kFailure;	
				_surf_faces[surf].push_back(_faces.size()-1);
			}
		}
		{
			// copy from temp
			MESH->m_VertCount	= _points.size();
			MESH->m_FaceCount	= _faces.size();
			MESH->m_Vertices	= xr_alloc<Fvector>(MESH->m_VertCount);
			Memory.mem_copy		(MESH->m_Vertices,&*_points.begin(),MESH->m_VertCount*sizeof(Fvector));
			MESH->m_Faces		= xr_alloc<st_Face>(MESH->m_FaceCount);
			Memory.mem_copy		(MESH->m_Faces,&*_faces.begin(),MESH->m_FaceCount*sizeof(st_Face));
			MESH->m_SmoothGroups = xr_alloc<u32>(MESH->m_FaceCount);
			Memory.mem_copy		(MESH->m_SmoothGroups,&*_sgs.begin(),MESH->m_FaceCount*sizeof(u32));

			MESH->RecomputeBBox	();
		}
		if ((MESH->GetVertexCount()<4)||(MESH->GetFaceCount()<2))
		{
			Log		("! Invalid mesh: '%s'. Faces<2 or Verts<4",*MESH->Name());
			return MS::kFailure;
		}
	}
	return stat;
}
    //---------------------------------------------------------------
    void LightExporter::exportLights ( SceneElement* sceneElement )
    {
        // If we have a external reference, we don't need to export the data here.
        if ( !sceneElement->getIsLocal() ) return;
        if ( !sceneElement->getIsExportNode () ) return;

        // Check if it is a light.
        SceneElement::Type sceneElementType = sceneElement->getType();
        if ( sceneElementType == SceneElement::LIGHT )
        {
            // Get the current dag path
            MDagPath dagPath = sceneElement->getPath();

            // Check if the current scene element isn't already exported.
            SceneGraph* sceneGraph = mDocumentExporter->getSceneGraph();
            if ( sceneGraph->findExportedElement ( dagPath ) ) return;

            // Check if the current element is an instance. 
            // We don't need to export instances, because we export the original instanced element.
            bool isInstance = ( dagPath.isInstanced() && dagPath.instanceNumber() > 0 );

            // If the original instanced element isn't already exported, we have to export it now.
            if ( isInstance )
            {
                // Get the original instanced element.
                MDagPath instancedPath;
                dagPath.getPath ( instancedPath, 0 );

                // Check if the original instanced element is already exported.
                SceneGraph* sceneGraph = mDocumentExporter->getSceneGraph();
                SceneElement* exportedElement = sceneGraph->findExportedElement ( instancedPath );
				if (exportedElement == 0)
				{
					// Export the original instanced element and push it in the exported scene graph. 
					if (exportLight(instancedPath))
					{
						SceneElement* instancedSceneElement = sceneGraph->findElement(instancedPath);
						SceneGraph* sceneGraph = mDocumentExporter->getSceneGraph();
						sceneGraph->addExportedElement(instancedSceneElement);
					}
				}
            }
            else
            {
                // Export the element and push it in the exported scene graph. 
                if ( exportLight ( dagPath ) )
                {
                    SceneGraph* sceneGraph = mDocumentExporter->getSceneGraph();
                    sceneGraph->addExportedElement( sceneElement );
                }
            }
        }


        // Recursive call for all the child elements
        for ( uint i=0; i<sceneElement->getChildCount(); ++i )
        {
            SceneElement* childElement = sceneElement->getChild ( i );
            exportLights ( childElement );
        }
    }
Пример #18
0
MStatus closestPointOnCurveCommand::redoIt()

{

   // DOUBLE-CHECK TO MAKE SURE THERE'S A SPECIFIED OBJECT TO EVALUATE ON:

   if (sList.length() == 0)

   {
	   MStatus stat;
	   MString msg = MStringResource::getString(kNoValidObject, stat);
       displayError(msg);
       return MStatus::kFailure;
   }



   // RETRIEVE THE SPECIFIED OBJECT AS A DAGPATH:

   MDagPath curveDagPath;
   sList.getDagPath(0, curveDagPath);


   // CHECK FOR INVALID NODE-TYPE INPUT WHEN SPECIFIED/SELECTED NODE IS *NOT* A "CURVE" NOR "CURVE TRANSFORM":

   if (!curveDagPath.node().hasFn(MFn::kNurbsCurve) && !(curveDagPath.node().hasFn(MFn::kTransform) && curveDagPath.hasFn(MFn::kNurbsCurve)))

   {
	   MStatus stat;
	   MString msg; 
	   // Use format to place variable string into message
	   MString msgFmt = MStringResource::getString(kInvalidType, stat);
	   MStringArray selectionStrings;
	   sList.getSelectionStrings(0, selectionStrings);
	   msg.format(msgFmt, selectionStrings[0]);
	   displayError(msg);
       return MStatus::kFailure;
   }



   // WHEN COMMAND *NOT* IN "QUERY MODE" (I.E. "CREATION MODE"), CREATE AND CONNECT A "closestPointOnCurve" NODE AND RETURN ITS NODE NAME:

   if (!queryFlagSet)

   {

      // CREATE THE NODE:

      MFnDependencyNode depNodeFn;

      if (closestPointOnCurveNodeName == "")

         depNodeFn.create("closestPointOnCurve");

      else

         depNodeFn.create("closestPointOnCurve", closestPointOnCurveNodeName);

      closestPointOnCurveNodeName = depNodeFn.name();



      // SET THE ".inPosition" ATTRIBUTE, IF SPECIFIED IN THE COMMAND:

      if (inPositionFlagSet)

      {

         MPlug inPositionXPlug = depNodeFn.findPlug("inPositionX");

         inPositionXPlug.setValue(inPosition.x);

         MPlug inPositionYPlug = depNodeFn.findPlug("inPositionY");

         inPositionYPlug.setValue(inPosition.y);

         MPlug inPositionZPlug = depNodeFn.findPlug("inPositionZ");

         inPositionZPlug.setValue(inPosition.z);

      }



      // MAKE SOME ADJUSTMENTS WHEN THE SPECIFIED NODE IS A "TRANSFORM" OF A CURVE SHAPE:

      unsigned instanceNumber=0;

      if (curveDagPath.node().hasFn(MFn::kTransform))

      {

         // EXTEND THE DAGPATH TO ITS CURVE "SHAPE" NODE:

         curveDagPath.extendToShape();



         // TRANSFORMS ARE *NOT* NECESSARILY THE "FIRST" INSTANCE TRANSFORM OF A CURVE SHAPE:

         instanceNumber = curveDagPath.instanceNumber();

      }



      // CONNECT THE NODES:

      MPlug worldCurvePlug, inCurvePlug;

      inCurvePlug = depNodeFn.findPlug("inCurve");

      depNodeFn.setObject(curveDagPath.node());

      worldCurvePlug = depNodeFn.findPlug("worldSpace");

      worldCurvePlug = worldCurvePlug.elementByLogicalIndex(instanceNumber);

      MDGModifier dgModifier;

      dgModifier.connect(worldCurvePlug, inCurvePlug);

      dgModifier.doIt();



      // SET COMMAND RESULT TO BE NEW NODE'S NAME, AND RETURN:

      setResult(closestPointOnCurveNodeName);

      return MStatus::kSuccess;

   }

   // OTHERWISE, WE'RE IN THE COMMAND'S "QUERY MODE":

   else

   {

      // COMPUTE THE CLOSEST POSITION, NORMAL, TANGENT, PARAMETER-U AND DISTANCE, USING THE *FIRST* INSTANCE TRANSFORM WHEN CURVE IS SPECIFIED AS A "SHAPE":

      MPoint position;

      MVector normal, tangent;

      double paramU, distance;

      closestTangentUAndDistance(curveDagPath, inPosition, position, normal, tangent, paramU, distance);



      // WHEN NO QUERYABLE FLAG IS SPECIFIED, INDICATE AN ERROR:

      if (!positionFlagSet && !normalFlagSet && !tangentFlagSet && !paramUFlagSet && !distanceFlagSet)

      {
		  MStatus stat;
		  MString msg = MStringResource::getString(kNoQueryFlag, stat);
		  displayError(msg);
          return MStatus::kFailure;
     }

      // WHEN JUST THE "DISTANCE" IS QUERIED, RETURN A SINGLE "FLOAT" INSTEAD OF AN ENTIRE FLOAT ARRAY FROM THE COMMAND:

      else if (distanceFlagSet && !(positionFlagSet || normalFlagSet || tangentFlagSet || paramUFlagSet))

         setResult(distance);

      // WHEN JUST THE "PARAMETER-U" IS QUERIED, RETURN A SINGLE "FLOAT" INSTEAD OF AN ENTIRE FLOAT ARRAY FROM THE COMMAND:

      else if (paramUFlagSet && !(positionFlagSet || normalFlagSet || tangentFlagSet || distanceFlagSet))

         setResult(paramU);

      // OTHERWISE, SET THE RETURN VALUE OF THE COMMAND'S RESULT TO A "COMPOSITE ARRAY OF FLOATS":

      else

      {

         // HOLDS FLOAT ARRAY RESULT:

         MDoubleArray floatArrayResult;



         // APPEND THE RESULTS OF THE CLOSEST POSITION, NORMAL, TANGENT, PARAMETER-U AND DISTANCE VALUES TO THE FLOAT ARRAY RESULT:

         if (positionFlagSet)

         {

            floatArrayResult.append(position.x);

            floatArrayResult.append(position.y);

            floatArrayResult.append(position.z);

         }

         if (normalFlagSet)

         {

            floatArrayResult.append(normal.x);

            floatArrayResult.append(normal.y);

            floatArrayResult.append(normal.z);

         }

         if (tangentFlagSet)

         {

            floatArrayResult.append(tangent.x);

            floatArrayResult.append(tangent.y);

            floatArrayResult.append(tangent.z);

         }

         if (paramUFlagSet)

            floatArrayResult.append(paramU);

         if (distanceFlagSet)

            floatArrayResult.append(distance);



         // FINALLY, SET THE COMMAND'S RESULT:

         setResult(floatArrayResult);

      }



      return MStatus::kSuccess;

   }

}
Пример #19
0
bool DX11ViewportRenderer::drawSurface( const MDagPath &dagPath, bool active, bool templated)
{
	bool drewSurface = false;

	if ( !dagPath.hasFn( MFn::kMesh ))
	{
		MMatrix  matrix = dagPath.inclusiveMatrix();
		MFnDagNode dagNode(dagPath);
		MBoundingBox box = dagNode.boundingBox();
		float color[3] = {0.6f, 0.3f, 0.0f};
		if (active)
		{
			color[0] = 1.0f;
			color[1] = 1.0f;
			color[2] = 1.0f;
		}
		else if (templated)
		{
			color[0] = 1.0f;
			color[1] = 0.686f;
			color[2] = 0.686f;
		}
		drawBounds( matrix, box, color);
		return true;
	}

	if ( dagPath.hasFn( MFn::kMesh ))
	{
		MMatrix  matrix = dagPath.inclusiveMatrix();
		MFnDagNode dagNode(dagPath);

		// Look for any hardware shaders which can draw D3D first.
		//
		bool drewWithHwShader = false;
		{
			MFnMesh fnMesh(dagPath);
			MObjectArray sets;
			MObjectArray comps;
			unsigned int instanceNum = dagPath.instanceNumber();
			if (!fnMesh.getConnectedSetsAndMembers(instanceNum, sets, comps, true))
				MGlobal::displayError("ERROR : MFnMesh::getConnectedSetsAndMembers");
			for ( unsigned i=0; i<sets.length(); i++ ) 
			{
				MObject set = sets[i];
				MObject comp = comps[i];

				MStatus status;
				MFnSet fnSet( set, &status );
				if (status == MS::kFailure) {
					MGlobal::displayError("ERROR: MFnSet::MFnSet");
					continue;
				}

				MObject shaderNode = findShader(set);
				if (shaderNode != MObject::kNullObj)
				{
					MPxHardwareShader * hwShader = 
						MPxHardwareShader::getHardwareShaderPtr( shaderNode );

					if (hwShader)
					{
						const MRenderProfile & profile = hwShader->profile();
						if (profile.hasRenderer( MRenderProfile::kMayaD3D))
						{
							// Render a Maya D3D hw shader here....
							//printf("Found a D3D hw shader\n");
							//drewWithHwShader = true;
						}
					}
				}
			}
		}

		// Get the geometry buffers for this bad boy and render them
		D3DGeometry* Geometry = m_resourceManager.getGeometry( dagPath, m_pD3DDevice);
		if( Geometry)
		{
			// Transform from object to world space
			//
			XMMATRIX objectToWorld = XMMATRIX
				(
				(float)matrix.matrix[0][0], (float)matrix.matrix[0][1], (float)matrix.matrix[0][2], (float)matrix.matrix[0][3],
				(float)matrix.matrix[1][0], (float)matrix.matrix[1][1], (float)matrix.matrix[1][2], (float)matrix.matrix[1][3],
				(float)matrix.matrix[2][0], (float)matrix.matrix[2][1], (float)matrix.matrix[2][2], (float)matrix.matrix[2][3],
				(float)matrix.matrix[3][0], (float)matrix.matrix[3][1], (float)matrix.matrix[3][2], (float)matrix.matrix[3][3]
			);

			FixedFunctionConstants cb;

			if (!drewWithHwShader)
			{
				// Get material properties for shader associated with mesh
				//
				// 1. Try to draw with the sample internal programmable shader
				bool drewGeometryWithShader = false;

				// 2. Draw with fixed function shader
				if (!drewGeometryWithShader)
				{
					// Set up a default material, just in case there is none.
					//
					float diffuse[3];
					if (active)
					{
						if (templated)
						{
							m_pD3DDeviceCtx->RSSetState( m_pWireframeRS );
							diffuse[0] = 1.0f; diffuse[1] = 0.686f; diffuse[2] = 0.686f;
						}
						else
						{
							m_pD3DDeviceCtx->RSSetState( m_pNormalRS );
							diffuse[0] = 0.6f; diffuse[1] = 0.6f; diffuse[2] = 0.6f;
						}
					}
					else
					{
						if (templated)
						{
							m_pD3DDeviceCtx->RSSetState( m_pWireframeRS );
							diffuse[0] = 1.0f; diffuse[1] = 0.686f; diffuse[2] = 0.686f;
						}
						else
						{
							m_pD3DDeviceCtx->RSSetState( m_pNormalRS );
							diffuse[0] = 0.5f; diffuse[1] = 0.5f; diffuse[2] = 0.5f;
						}
					}

					// Set constant buffer
					XMVECTOR det;
					cb.wvIT = XMMatrixInverse( &det, objectToWorld * m_currentViewMatrix );
					cb.wvp = XMMatrixTranspose( objectToWorld * m_currentViewMatrix * m_currentProjectionMatrix );
					cb.wv = XMMatrixTranspose( objectToWorld * m_currentViewMatrix );
					cb.lightDir = XMFLOAT4( 0.0f, 0.0f, 1.0f, 0.0f );
					cb.lightColor = XMFLOAT4( 1.0f, 1.0f, 1.0f, 0.0f );
					cb.ambientLight = XMFLOAT4( 0.2f, 0.2f, 0.2f, 0.0f );
					cb.diffuseMaterial = XMFLOAT4( diffuse[0], diffuse[1], diffuse[2], 0.0f );
					cb.specularColor = XMFLOAT4( 0.2f, 0.2f, 0.2f, 0.0f );
					cb.diffuseCoeff = 1.0f;
					cb.shininess = 16.0f;
					cb.transparency = 1.0f;
					m_pD3DDeviceCtx->UpdateSubresource( m_pFixedFunctionConstantBuffer, 0, NULL, &cb, 0, 0 );

					// get shader
					SurfaceEffectItemList::const_iterator it = m_resourceManager.getSurfaceEffectItemList().find( "Maya_fixedFunction" );
					if ( it == m_resourceManager.getSurfaceEffectItemList().end() )
						return false;
					const SurfaceEffectItem* sei = it->second;

					// bind shaders
					m_pD3DDeviceCtx->VSSetShader( sei->fVertexShader, NULL, 0 );
					m_pD3DDeviceCtx->VSSetConstantBuffers( 0, 1, &m_pFixedFunctionConstantBuffer );
					m_pD3DDeviceCtx->IASetInputLayout( sei->fInputLayout );
					m_pD3DDeviceCtx->PSSetShader( sei->fPixelShader, NULL, 0 );
					m_pD3DDeviceCtx->PSSetConstantBuffers( 0, 1, &m_pFixedFunctionConstantBuffer );

					Geometry->Render( m_pD3DDeviceCtx );

					drewSurface = true;
				}
			}

			// Draw wireframe on top
			//

			if ( drewSurface && active )
			{
				bool drawActiveWithBounds = false;
				if (drawActiveWithBounds)
				{
					MBoundingBox box = dagNode.boundingBox();
					float color[3] = {1.0f, 1.0f, 1.0f};
					drawBounds( matrix, box, color );
				}
				else
				{
					cb.lightColor = XMFLOAT4( 0.0f, 0.0f, 0.0f, 0.0f );
					cb.ambientLight = XMFLOAT4( 1.0f, 1.0f, 1.0f, 0.0f );
					cb.diffuseMaterial = XMFLOAT4( 1.0f, 1.0f, 1.0f, 0.0f );
					cb.specularColor = XMFLOAT4( 0.0f, 0.0f, 0.0f, 0.0f );
					m_pD3DDeviceCtx->UpdateSubresource( m_pFixedFunctionConstantBuffer, 0, NULL, &cb, 0, 0 );

					m_pD3DDeviceCtx->RSSetState( m_pWireframeRS );

					Geometry->Render( m_pD3DDeviceCtx );				
				}
			}
		} // If Geometry
	}
	return drewSurface;
}
Пример #20
0
MStatus pointOnMeshCommand::redoIt()

{

    // WHEN NO MESH IS SPECIFIED IN THE COMMAND, GET THE FIRST SELECTED MESH FROM THE SELECTION LIST:

    MSelectionList sList;

    if (meshNodeName=="")

    {

        MGlobal::getActiveSelectionList(sList);

        if (sList.length()==0)

        {

            displayError("No mesh or mesh transform specified!");

            return MS::kFailure;

        }

    }

    // OTHERWISE, USE THE NODE NAME SPECIFIED IN THE LAST ARGUMENT OF THE COMMAND:

    else if (sList.add(meshNodeName) == MS::kInvalidParameter)

    {

        displayError("Specified mesh does not exist!");

        return MS::kFailure;

    }



    // RETRIEVE THE FIRST ITEM FROM THE SELECTION LIST:

    MDagPath meshDagPath;

    sList.getDagPath(0, meshDagPath);



    // CREATE AND CONNECT A "pointOnMeshInfo" NODE, OR GET THE POINT AND NORMAL ACCORDING TO

    // WHETHER THE "-position/-p" AND/OR "-normal/-nr" FLAGS WERE SPECIFIED, AND WHETHER THE MESH

    // "SHAPE" OR ITS "TRANSFORM" WAS SPECIFIED/SELECTED:

    MPoint point;

    MVector normal;

    // WHEN THE SPECIFIED NODE IS THE MESH "SHAPE":

    if (meshDagPath.node().hasFn(MFn::kMesh))

    {

        // WHEN NEITHER "-position/-p" NOR "-normal/-nr" ARE SPECIFIED, CREATE AND CONNECT A "pointOnMeshInfo" NODE AND RETURN ITS NODE NAME:

        if (!positionSpecified && !normalSpecified)

        {

            // CREATE THE NODE:

            nodeCreated = true;

            MFnDependencyNode depNodeFn;

            if (pointOnMeshInfoName == "")

                depNodeFn.create("pointOnMeshInfo");

            else

                depNodeFn.create("pointOnMeshInfo", pointOnMeshInfoName);

            pointOnMeshInfoName = depNodeFn.name();



            // SET THE ".faceIndex" ATTRIBUTE, IF SPECIFIED IN THE COMMAND:

            if (faceIndexSpecified)

            {

                MPlug faceIndexPlug = depNodeFn.findPlug("faceIndex");

                faceIndexPlug.setValue(faceIndex);

            }



            // SET THE ".relative" ATTRIBUTE, IF SPECIFIED IN THE COMMAND:

            if (relativeSpecified)

            {

                MPlug relativePlug = depNodeFn.findPlug("relative");

                relativePlug.setValue(relative);

            }



            // SET THE ".parameterU" ATTRIBUTE, IF SPECIFIED IN THE COMMAND:

            if (parameterUSpecified)

            {

                MPlug parameterUPlug = depNodeFn.findPlug("parameterU");

                parameterUPlug.setValue(parameterU);

            }



            // SET THE ".parameterV" ATTRIBUTE, IF SPECIFIED IN THE COMMAND:

            if (parameterVSpecified)

            {

                MPlug parameterVPlug = depNodeFn.findPlug("parameterV");

                parameterVPlug.setValue(parameterV);

            }



            // CONNECT THE NODES:

            MPlug worldMeshPlug, inMeshPlug;

            inMeshPlug = depNodeFn.findPlug("inMesh");

            depNodeFn.setObject(meshDagPath.node());

            worldMeshPlug = depNodeFn.findPlug("worldMesh");

            worldMeshPlug = worldMeshPlug.elementByLogicalIndex(0);  // ASSUME THE *FIRST* INSTANCE OF THE MESH IS REQUESTED FOR MESH SHAPES.

            MDGModifier dgModifier;

            dgModifier.connect(worldMeshPlug, inMeshPlug);

            dgModifier.doIt();



            // SET COMMAND RESULT AND RETURN:

            setResult(pointOnMeshInfoName);

            return MStatus::kSuccess;

        }

        // OTHERWISE, COMPUTE THE POINT-POSITION AND NORMAL, USING THE *FIRST* INSTANCE'S TRANSFORM:

        else

            getPointAndNormal(meshDagPath, faceIndex, relative, parameterU, parameterV, point, normal);

    }

    // WHEN THE SPECIFIED NODE IS A "TRANSFORM" OF A MESH SHAPE:

    else if (meshDagPath.node().hasFn(MFn::kTransform) && meshDagPath.hasFn(MFn::kMesh))

    {

        // WHEN NEITHER "-position/-p" NOR "-normal/-nr" ARE SPECIFIED, CREATE AND CONNECT A "pointOnMeshInfo" NODE AND RETURN ITS NODE NAME:

        if (!positionSpecified && !normalSpecified)

        {

            // CREATE THE NODE:

            nodeCreated = true;

            meshDagPath.extendToShape();

            MFnDependencyNode depNodeFn;

            if (pointOnMeshInfoName == "")

                depNodeFn.create("pointOnMeshInfo");

            else

                depNodeFn.create("pointOnMeshInfo", pointOnMeshInfoName);

            pointOnMeshInfoName = depNodeFn.name();



            // SET THE ".faceIndex" ATTRIBUTE, IF SPECIFIED IN THE COMMAND:

            if (faceIndexSpecified)

            {

                MPlug faceIndexPlug = depNodeFn.findPlug("faceIndex");

                faceIndexPlug.setValue(faceIndex);

            }



            // SET THE ".relative" ATTRIBUTE, IF SPECIFIED IN THE COMMAND:

            if (relativeSpecified)

            {

                MPlug relativePlug = depNodeFn.findPlug("relative");

                relativePlug.setValue(relative);

            }



            // SET THE ".parameterU" ATTRIBUTE, IF SPECIFIED IN THE COMMAND:

            if (parameterUSpecified)

            {

                MPlug parameterUPlug = depNodeFn.findPlug("parameterU");

                parameterUPlug.setValue(parameterU);

            }



            // SET THE ".parameterV" ATTRIBUTE, IF SPECIFIED IN THE COMMAND:

            if (parameterVSpecified)

            {

                MPlug parameterVPlug = depNodeFn.findPlug("parameterV");

                parameterVPlug.setValue(parameterV);

            }



            // CONNECT THE NODES:

            MPlug worldMeshPlug, inMeshPlug;

            inMeshPlug = depNodeFn.findPlug("inMesh");

            depNodeFn.setObject(meshDagPath.node());

            worldMeshPlug = depNodeFn.findPlug("worldMesh");

            worldMeshPlug = worldMeshPlug.elementByLogicalIndex(meshDagPath.instanceNumber());

            MDGModifier dgModifier;

            dgModifier.connect(worldMeshPlug, inMeshPlug);

            dgModifier.doIt();



            // SET COMMAND RESULT AND RETURN:

            setResult(pointOnMeshInfoName);

            return MStatus::kSuccess;

        }

        // OTHERWISE, COMPUTE THE POINT-POSITION AND NORMAL:

        else

            getPointAndNormal(meshDagPath, faceIndex, relative, parameterU, parameterV, point, normal);

    }

    // INVALID INPUT WHEN SPECIFIED/SELECTED NODE IS NOT A MESH NOR TRANSFORM:

    else

    {

        displayError("Invalid type!  Only a mesh or its transform can be specified!");

        return MStatus::kFailure;

    }



    // SET THE RETURN VALUES OF THE COMMAND'S RESULT TO BE AN ARRAY OF FLOATS OUTPUTTING THE POSITION AND/OR NORMAL:

    MDoubleArray result;

    if (positionSpecified)

    {

        result.append(point.x);

        result.append(point.y);

        result.append(point.z);

    }

    if (normalSpecified)

    {

        result.append(normal.x);

        result.append(normal.y);

        result.append(normal.z);

    }

    setResult(result);



    return MStatus::kSuccess;

}