Example #1
0
MStatus AlembicNode::compute(const MPlug & plug, MDataBlock & dataBlock)
{
    MStatus status;

    // update the frame number to be imported
    MDataHandle speedHandle = dataBlock.inputValue(mSpeedAttr, &status);
    double speed = speedHandle.asDouble();

    MDataHandle offsetHandle = dataBlock.inputValue(mOffsetAttr, &status);
    double offset = offsetHandle.asDouble();

    MDataHandle timeHandle = dataBlock.inputValue(mTimeAttr, &status);
    MTime t = timeHandle.asTime();
    double inputTime = t.as(MTime::kSeconds);

    double fps = getFPS();

    // scale and offset inputTime.
    inputTime = computeAdjustedTime(inputTime, speed, offset/fps);

    // this should be done only once per file
	if (mFileInitialized == false)
	{
		mFileInitialized = true;

		//Get list of input filenames
		MFnDependencyNode depNode(thisMObject());
		MPlug layerFilesPlug = depNode.findPlug("abc_layerFiles");
		MFnStringArrayData fnSAD( layerFilesPlug.asMObject() );
		MStringArray storedFilenames = fnSAD.array();

		//Legacy support for single-filename input
		if( storedFilenames.length() == 0 )
		{
			MFileObject fileObject;
			MDataHandle dataHandle = dataBlock.inputValue(mAbcFileNameAttr);
			fileObject.setRawFullName(dataHandle.asString());
			MString fileName = fileObject.resolvedFullName();
			storedFilenames.append( fileName );
		}

		std::vector<std::string> abcFilenames;
		for(unsigned int i = 0; i < storedFilenames.length(); i++)
			abcFilenames.push_back( storedFilenames[i].asChar() );

		Alembic::Abc::IArchive archive;
		Alembic::AbcCoreFactory::IFactory factory;
		factory.setPolicy(Alembic::Abc::ErrorHandler::kQuietNoopPolicy);

		archive = factory.getArchive( abcFilenames );

		if (!archive.valid())
		{
			MString theError = "Error opening these alembic files: ";

			const unsigned int numFilenames = storedFilenames.length();
			for( unsigned int i = 0; i < numFilenames; i++ )
			{
				theError += storedFilenames[ i ];

				if( i != (numFilenames - 1) )
					theError += ", ";
			}

			printError(theError);
		}

		// initialize some flags for plug update
		mSubDInitialized = false;
		mPolyInitialized = false;

		// When an alembic cache will be imported at the first time using
		// AbcImport, we need to set mIncludeFilterAttr (filterHandle) to be
		// mIncludeFilterString for later use. When we save a maya scene(.ma)
		// mIncludeFilterAttr will be saved. Then when we load the saved
		// .ma file, mIncludeFilterString will be set to be mIncludeFilterAttr.
		MDataHandle includeFilterHandle =
						dataBlock.inputValue(mIncludeFilterAttr, &status);
		MString& includeFilterString = includeFilterHandle.asString();

	   if (mIncludeFilterString.length() > 0)
		{
			includeFilterHandle.set(mIncludeFilterString);
			dataBlock.setClean(mIncludeFilterAttr);
		}
		else if (includeFilterString.length() > 0)
		{
			mIncludeFilterString = includeFilterString;
		}

		MDataHandle excludeFilterHandle =
						dataBlock.inputValue(mExcludeFilterAttr, &status);
		MString& excludeFilterString = excludeFilterHandle.asString();

	   if (mExcludeFilterString.length() > 0)
		{
			excludeFilterHandle.set(mExcludeFilterString);
			dataBlock.setClean(mExcludeFilterAttr);
		}
		else if (excludeFilterString.length() > 0)
		{
			mExcludeFilterString = excludeFilterString;
		}


		MFnDependencyNode dep(thisMObject());
		MPlug allSetsPlug = dep.findPlug("allColorSets");
		CreateSceneVisitor visitor(inputTime, !allSetsPlug.isNull(),
			MObject::kNullObj, CreateSceneVisitor::NONE, "",
			mIncludeFilterString, mExcludeFilterString);

		visitor.walk(archive);

		if (visitor.hasSampledData())
		{
			// information retrieved from the hierarchy traversal
			// and given to AlembicNode to provide update
			visitor.getData(mData);
			mData.getFrameRange(mSequenceStartTime, mSequenceEndTime);
			MDataHandle startFrameHandle = dataBlock.inputValue(mStartFrameAttr,
																&status);
			startFrameHandle.set(mSequenceStartTime*fps);
			MDataHandle endFrameHandle = dataBlock.inputValue(mEndFrameAttr,
																&status);
			endFrameHandle.set(mSequenceEndTime*fps);
		}
	}

    // Retime
    MDataHandle cycleHandle = dataBlock.inputValue(mCycleTypeAttr, &status);
    short playType = cycleHandle.asShort();
    inputTime = computeRetime(inputTime, mSequenceStartTime, mSequenceEndTime,
                              playType);

    clamp<double>(mSequenceStartTime, mSequenceEndTime, inputTime);

    // update only when the time lapse is big enough
    if (fabs(inputTime - mCurTime) > 0.00001)
    {
        mOutRead = std::vector<bool>(mOutRead.size(), false);
        mCurTime = inputTime;
    }

    if (plug == mOutPropArrayAttr)
    {

        if (mOutRead[0])
        {
            dataBlock.setClean(plug);
            return MS::kSuccess;
        }

        mOutRead[0] = true;

        unsigned int propSize =
            static_cast<unsigned int>(mData.mPropList.size());

        if (propSize > 0)
        {
            MArrayDataHandle outArrayHandle = dataBlock.outputValue(
                mOutPropArrayAttr, &status);

            unsigned int outHandleIndex = 0;
            MDataHandle outHandle;

            // for all of the nodes with sampled attributes
            for (unsigned int i = 0; i < propSize; i++)
            {
                // only use the handle if it matches the index.
                // The index wont line up in the sparse case so we
                // can just skip that element.
                if (outArrayHandle.elementIndex() == outHandleIndex++)
                {
                    outHandle = outArrayHandle.outputValue();
                }
                else
                {
                    continue;
                }

                if (mData.mPropList[i].mArray.valid())
                {
                    readProp(mCurTime, mData.mPropList[i].mArray, outHandle);
                }
                else if (mData.mPropList[i].mScalar.valid())
                {
                    // for visibility only
                    if (mData.mPropList[i].mScalar.getName() ==
                        Alembic::AbcGeom::kVisibilityPropertyName)
                    {
                        Alembic::Util::int8_t visVal = 1;
                        mData.mPropList[i].mScalar.get(&visVal,
                            Alembic::Abc::ISampleSelector(mCurTime,
                                Alembic::Abc::ISampleSelector::kNearIndex ));
                        outHandle.setGenericBool(visVal != 0, false);
                    }
                    else
                    {
                        // for all scalar props
                        readProp(mCurTime, mData.mPropList[i].mScalar, outHandle);
                    }
                }
                outArrayHandle.next();
            }
            outArrayHandle.setAllClean();
        }

    }
    else if (plug == mOutTransOpArrayAttr )
    {
        if (mOutRead[1])
        {
            dataBlock.setClean(plug);
            return MS::kSuccess;
        }

        mOutRead[1] = true;

        unsigned int xformSize =
            static_cast<unsigned int>(mData.mXformList.size());

        if (xformSize > 0)
        {
            MArrayDataHandle outArrayHandle =
                dataBlock.outputValue(mOutTransOpArrayAttr, &status);

            MPlug arrayPlug(thisMObject(), mOutTransOpArrayAttr);

            MDataHandle outHandle;
            unsigned int outHandleIndex = 0;

            for (unsigned int i = 0; i < xformSize; i++)
            {
                std::vector<double> sampleList;

                if (mData.mIsComplexXform[i])
                {
                    readComplex(mCurTime, mData.mXformList[i], sampleList);
                }
                else
                {
                    Alembic::AbcGeom::XformSample samp;
                    read(mCurTime, mData.mXformList[i], sampleList, samp);
                }

                unsigned int sampleSize = (unsigned int)sampleList.size();

                for (unsigned int j = 0; j < sampleSize; j++)
                {
                    // only use the handle if it matches the index.
                    // The index wont line up in the sparse case so we
                    // can just skip that element.
                    if (outArrayHandle.elementIndex() == outHandleIndex++)
                    {
                        outHandle = outArrayHandle.outputValue(&status);
                    }
                    else
                        continue;

                    outArrayHandle.next();
                    outHandle.set(sampleList[j]);
                }
            }
            outArrayHandle.setAllClean();
        }
    }
    else if (plug == mOutLocatorPosScaleArrayAttr )
    {
        if (mOutRead[8])
        {
            dataBlock.setClean(plug);
            return MS::kSuccess;
        }

        mOutRead[8] = true;

        unsigned int locSize =
            static_cast<unsigned int>(mData.mLocList.size());

        if (locSize > 0)
        {
            MArrayDataHandle outArrayHandle =
                dataBlock.outputValue(mOutLocatorPosScaleArrayAttr, &status);

            MPlug arrayPlug(thisMObject(), mOutLocatorPosScaleArrayAttr);

            MDataHandle outHandle;
            unsigned int outHandleIndex = 0;

            for (unsigned int i = 0; i < locSize; i++)
            {
                std::vector< double > sampleList;
                read(mCurTime, mData.mLocList[i], sampleList);

                unsigned int sampleSize = (unsigned int)sampleList.size();
                for (unsigned int j = 0; j < sampleSize; j++)
                {
                    // only use the handle if it matches the index.
                    // The index wont line up in the sparse case so we
                    // can just skip that element.
                    if (outArrayHandle.elementIndex() == outHandleIndex++)
                    {
                        outHandle = outArrayHandle.outputValue(&status);
                    }
                    else
                        continue;

                    outArrayHandle.next();
                    outHandle.set(sampleList[j]);
                }
            }
            outArrayHandle.setAllClean();
        }
    }
    else if (plug == mOutSubDArrayAttr)
    {
        if (mOutRead[2])
        {
            // Reference the output to let EM know we are the writer
            // of the data. EM sets the output to holder and causes
            // race condition when evaluating fan-out destinations.
            MArrayDataHandle outArrayHandle =
                dataBlock.outputValue(mOutSubDArrayAttr, &status);
            const unsigned int elementCount = outArrayHandle.elementCount();
            for (unsigned int j = 0; j < elementCount; j++)
            {
                outArrayHandle.outputValue().data();
                outArrayHandle.next();
            }
            outArrayHandle.setAllClean();
            return MS::kSuccess;
        }

        mOutRead[2] = true;

        unsigned int subDSize =
            static_cast<unsigned int>(mData.mSubDList.size());

        if (subDSize > 0)
        {
            MArrayDataHandle outArrayHandle = dataBlock.outputValue(
                mOutSubDArrayAttr, &status);

            MDataHandle outHandle;

            for (unsigned int j = 0; j < subDSize; j++)
            {
                // these elements can be sparse if they have been deleted
                if (outArrayHandle.elementIndex() != j)
                {
                    continue;
                }

                outHandle = outArrayHandle.outputValue(&status);
                outArrayHandle.next();

                MObject obj = outHandle.data();
                if (obj.hasFn(MFn::kMesh))
                {
                    MFnMesh fnMesh(obj);
                    readSubD(mCurTime, fnMesh, obj, mData.mSubDList[j],
                        mSubDInitialized);
                    outHandle.set(obj);
                }
            }
            mSubDInitialized = true;
            outArrayHandle.setAllClean();
        }
        // for the case where we don't have any nodes, we want to make sure
        // to push out empty meshes on our connections, this can happen if
        // the input file was offlined, currently we only need to do this for
        // meshes as Nurbs, curves, and the other channels don't crash Maya
        else
        {
            MArrayDataHandle outArrayHandle = dataBlock.outputValue(
                mOutSubDArrayAttr, &status);

            if (outArrayHandle.elementCount() > 0)
            {
                do
                {
                    MDataHandle outHandle = outArrayHandle.outputValue();
                    MObject obj = outHandle.data();
                    if (obj.hasFn(MFn::kMesh))
                    {
                        MFloatPointArray emptyVerts;
                        MIntArray emptyCounts;
                        MIntArray emptyConnects;
                        MFnMesh emptyMesh;
                        emptyMesh.create(0, 0, emptyVerts, emptyCounts,
                            emptyConnects, obj);
                        outHandle.set(obj);
                    }
                }
                while (outArrayHandle.next() == MS::kSuccess);
            }
            mSubDInitialized = true;
            outArrayHandle.setAllClean();
        }
    }
    else if (plug == mOutPolyArrayAttr)
    {
        if (mOutRead[3])
        {
            // Reference the output to let EM know we are the writer
            // of the data. EM sets the output to holder and causes
            // race condition when evaluating fan-out destinations.
            MArrayDataHandle outArrayHandle =
                dataBlock.outputValue(mOutPolyArrayAttr, &status);
            const unsigned int elementCount = outArrayHandle.elementCount();
            for (unsigned int j = 0; j < elementCount; j++)
            {
                outArrayHandle.outputValue().data();
                outArrayHandle.next();
            }
            outArrayHandle.setAllClean();
            return MS::kSuccess;
        }

        mOutRead[3] = true;

        unsigned int polySize =
            static_cast<unsigned int>(mData.mPolyMeshList.size());

        if (polySize > 0)
        {
            MArrayDataHandle outArrayHandle =
                dataBlock.outputValue(mOutPolyArrayAttr, &status);

            MDataHandle outHandle;

            for (unsigned int j = 0; j < polySize; j++)
            {
                // these elements can be sparse if they have been deleted
                if (outArrayHandle.elementIndex() != j)
                {
                    continue;
                }

                outHandle = outArrayHandle.outputValue(&status);
                outArrayHandle.next();

                MObject obj = outHandle.data();
                if (obj.hasFn(MFn::kMesh))
                {
                    MFnMesh fnMesh(obj);
                    readPoly(mCurTime, fnMesh, obj, mData.mPolyMeshList[j],
                        mPolyInitialized);
                    outHandle.set(obj);
                }
            }
            mPolyInitialized = true;
            outArrayHandle.setAllClean();
        }
        // for the case where we don't have any nodes, we want to make sure
        // to push out empty meshes on our connections, this can happen if
        // the input file was offlined, currently we only need to do this for
        // meshes as Nurbs, curves, and the other channels don't crash Maya
        else
        {
            MArrayDataHandle outArrayHandle = dataBlock.outputValue(
                mOutPolyArrayAttr, &status);

            if (outArrayHandle.elementCount() > 0)
            {
                do
                {
                    MDataHandle outHandle = outArrayHandle.outputValue(&status);
                    MObject obj = outHandle.data();
                    if (obj.hasFn(MFn::kMesh))
                    {
                        MFloatPointArray emptyVerts;
                        MIntArray emptyCounts;
                        MIntArray emptyConnects;
                        MFnMesh emptyMesh;
                        emptyMesh.create(0, 0, emptyVerts, emptyCounts,
                            emptyConnects, obj);
                        outHandle.set(obj);
                    }
                }
                while (outArrayHandle.next() == MS::kSuccess);
            }
            mPolyInitialized = true;
            outArrayHandle.setAllClean();
        }
    }
    else if (plug == mOutCameraArrayAttr)
    {
        if (mOutRead[4])
        {
            dataBlock.setClean(plug);
            return MS::kSuccess;
        }

        mOutRead[4] = true;

        unsigned int cameraSize =
            static_cast<unsigned int>(mData.mCameraList.size());

        if (cameraSize > 0)
        {
            MArrayDataHandle outArrayHandle =
                dataBlock.outputValue(mOutCameraArrayAttr, &status);
            MPlug arrayPlug(thisMObject(), mOutCameraArrayAttr);
            double angleConversion = 1.0;

            switch (MAngle::uiUnit())
            {
                case MAngle::kRadians:
                    angleConversion = 0.017453292519943295;
                break;
                case MAngle::kAngMinutes:
                    angleConversion = 60.0;
                break;
                case MAngle::kAngSeconds:
                    angleConversion = 3600.0;
                break;
                default:
                break;
            }

            MDataHandle outHandle;
            unsigned int index = 0;

            for (unsigned int cameraIndex = 0; cameraIndex < cameraSize;
                cameraIndex++)
            {
                Alembic::AbcGeom::ICamera & cam =
                    mData.mCameraList[cameraIndex];
                std::vector<double> array;

                read(mCurTime, cam, array);

                for (unsigned int dataIndex = 0; dataIndex < array.size();
                    dataIndex++, index++)
                {
                    // skip over sparse elements
                    if (index != outArrayHandle.elementIndex())
                    {
                        continue;
                    }

                    outHandle = outArrayHandle.outputValue(&status);
                    outArrayHandle.next();

                    // not shutter angle index, so not an angle
                    if (dataIndex != 11)
                    {
                        outHandle.set(array[dataIndex]);
                    }
                    else
                    {
                        outHandle.set(array[dataIndex] * angleConversion);
                    }
                }  // for the per camera data handles
            }  // for each camera
            outArrayHandle.setAllClean();
        }
    }
    else if (plug == mOutNurbsSurfaceArrayAttr)
    {
        if (mOutRead[5])
        {
            // Reference the output to let EM know we are the writer
            // of the data. EM sets the output to holder and causes
            // race condition when evaluating fan-out destinations.
            MArrayDataHandle outArrayHandle =
                dataBlock.outputValue(mOutNurbsSurfaceArrayAttr, &status);
            const unsigned int elementCount = outArrayHandle.elementCount();
            for (unsigned int j = 0; j < elementCount; j++)
            {
                outArrayHandle.outputValue().data();
                outArrayHandle.next();
            }
            outArrayHandle.setAllClean();
            return MS::kSuccess;
        }

        mOutRead[5] = true;

        unsigned int nSurfaceSize =
            static_cast<unsigned int>(mData.mNurbsList.size());

        if (nSurfaceSize > 0)
        {
            MArrayDataHandle outArrayHandle =
                dataBlock.outputValue(mOutNurbsSurfaceArrayAttr, &status);

            MDataHandle outHandle;

            for (unsigned int j = 0; j < nSurfaceSize; j++)
            {
                // these elements can be sparse if they have been deleted
                if (outArrayHandle.elementIndex() != j)
                    continue;

                outHandle = outArrayHandle.outputValue(&status);
                outArrayHandle.next();

                MObject obj = outHandle.data();
                if (obj.hasFn(MFn::kNurbsSurface))
                {
                    readNurbs(mCurTime, mData.mNurbsList[j], obj);
                    outHandle.set(obj);
                }
            }
            outArrayHandle.setAllClean();
        }
    }
    else if (plug == mOutNurbsCurveGrpArrayAttr)
    {
        if (mOutRead[6])
        {
            // Reference the output to let EM know we are the writer
            // of the data. EM sets the output to holder and causes
            // race condition when evaluating fan-out destinations.
            MArrayDataHandle outArrayHandle =
                dataBlock.outputValue(mOutNurbsCurveGrpArrayAttr, &status);
            const unsigned int elementCount = outArrayHandle.elementCount();
            for (unsigned int j = 0; j < elementCount; j++)
            {
                outArrayHandle.outputValue().data();
                outArrayHandle.next();
            }
            outArrayHandle.setAllClean();
            return MS::kSuccess;
        }

        mOutRead[6] = true;

        unsigned int nCurveGrpSize =
            static_cast<unsigned int>(mData.mCurvesList.size());

        if (nCurveGrpSize > 0)
        {
            MArrayDataHandle outArrayHandle =
                dataBlock.outputValue(mOutNurbsCurveGrpArrayAttr, &status);
            MDataHandle outHandle;

            std::vector<MObject> curvesObj;
            for (unsigned int i = 0; i < nCurveGrpSize; ++i)
            {
                readCurves(mCurTime, mData.mCurvesList[i],
                    mData.mNumCurves[i], curvesObj);
            }

            std::size_t numChild = curvesObj.size();

            // not the best way to do this
            // only reading bunches of curves based on the connections would be
            // more efficient when there is a bunch of broken connections
            for (unsigned int i = 0; i < numChild; i++)
            {
                if (outArrayHandle.elementIndex() != i)
                {
                    continue;
                }

                outHandle = outArrayHandle.outputValue(&status);
                outArrayHandle.next();
                status = outHandle.set(curvesObj[i]);
            }

            outArrayHandle.setAllClean();
        }
    }
    else
    {
        return MS::kUnknownParameter;
    }

    dataBlock.setClean(plug);
    return status;
}
void liqBoundingBoxLocator::draw( M3dView & view, 
                                  const MDagPath & path,
                                  M3dView::DisplayStyle style, 
                                  M3dView::DisplayStatus status )
{ 
	MFnDagNode dagFn( thisMObject() );
	MFnDagNode transFn( dagFn.parent( 0 ) );

	MStatus stat;

	bool drawBox( 0 );
	MPlug plug = dagFn.findPlug( "drawBox", stat );
	if ( stat == MS::kSuccess ) plug.getValue( drawBox );
	if ( !drawBox ) return;

	MDoubleArray bb( 6 );
	MGlobal::executeCommand( MString( "exactWorldBoundingBox " ) + transFn.fullPathName(), bb );

	pts = shared_array< MPoint >( new MPoint[ 8 ] );

	pts[0].x = bb[0];
	pts[0].y = bb[4];
	pts[0].z = bb[2];

	pts[1].x = bb[0];
	pts[1].y = bb[4];
	pts[1].z = bb[5];

	pts[2].x = bb[3];
	pts[2].y = bb[4];
	pts[2].z = bb[5];

	pts[3].x = bb[3];
	pts[3].y = bb[4];
	pts[3].z = bb[2];

	pts[4].x = bb[0];
	pts[4].y = bb[1];
	pts[4].z = bb[2];

	pts[5].x = bb[0];
	pts[5].y = bb[1];
	pts[5].z = bb[5];

	pts[6].x = bb[3];
	pts[6].y = bb[1];
	pts[6].z = bb[5];

	pts[7].x = bb[3];
	pts[7].y = bb[1];
	pts[7].z = bb[2];

	MMatrix m( path.inclusiveMatrix() );

	for( unsigned i( 0 ); i < 8; i++ )
		pts[i] *= m.inverse();

	// draw box
	view.beginGL();
	view.setDrawColor( MColor( .57f, 0, .57f ) );
	glPushAttrib( GL_CURRENT_BIT );

	glBegin(GL_LINE_STRIP);
	glVertex3f( (float)pts[0].x, (float)pts[0].y, (float)pts[0].z );
	glVertex3f( (float)pts[1].x, (float)pts[1].y, (float)pts[1].z );
	glVertex3f( (float)pts[2].x, (float)pts[2].y, (float)pts[2].z );
	glVertex3f( (float)pts[3].x, (float)pts[3].y, (float)pts[3].z );
	glVertex3f( (float)pts[0].x, (float)pts[0].y, (float)pts[0].z );
	glEnd();
	glBegin(GL_LINE_STRIP);
	glVertex3f( (float)pts[4].x, (float)pts[4].y, (float)pts[4].z );
	glVertex3f( (float)pts[5].x, (float)pts[5].y, (float)pts[5].z );
	glVertex3f( (float)pts[6].x, (float)pts[6].y, (float)pts[6].z );
	glVertex3f( (float)pts[7].x, (float)pts[7].y, (float)pts[7].z );
	glVertex3f( (float)pts[4].x, (float)pts[4].y, (float)pts[4].z );
	glEnd();
	glBegin(GL_LINE_STRIP);
	glVertex3f( (float)pts[0].x, (float)pts[0].y, (float)pts[0].z );
	glVertex3f( (float)pts[4].x, (float)pts[4].y, (float)pts[4].z );
	glEnd();
	glBegin(GL_LINE_STRIP);
	glVertex3f( (float)pts[1].x, (float)pts[1].y, (float)pts[1].z );
	glVertex3f( (float)pts[5].x, (float)pts[5].y, (float)pts[5].z );
	glEnd();
	glBegin(GL_LINE_STRIP);
	glVertex3f( (float)pts[2].x, (float)pts[2].y, (float)pts[2].z );
	glVertex3f( (float)pts[6].x, (float)pts[6].y, (float)pts[6].z );
	glEnd();
	glBegin(GL_LINE_STRIP);
	glVertex3f( (float)pts[3].x, (float)pts[3].y, (float)pts[3].z );
	glVertex3f( (float)pts[7].x, (float)pts[7].y, (float)pts[7].z );
	glEnd();
	view.endGL();
}
Example #3
0
// Compute takes two parameters: plug and data.
// - Plug is the the data value that needs to be recomputed
// - Data provides handles to all of the nodes attributes, only these
//   handles should be used when performing computations.
//
MStatus mix::compute( const MPlug& plug, MDataBlock& block )
{
    // The plug parameter will allow us to determine which output attribute
    // needs to be calculated.
    //
	if( plug == aOutColor || plug == aOutTransparency || plug.parent() == aOutColor || plug.parent() == aOutTransparency  )
    {
        MStatus status;
        MFloatVector resultColor( 0.0, 0.0, 0.0 );

        // Get surface shading parameters from input block
        //
        MFloatVector& surfaceNormal = block.inputValue( aNormalCamera, &status ).asFloatVector();
        CHECK_MSTATUS( status );

        MFloatVector& surfaceColor = block.inputValue( aColor, &status ).asFloatVector();
        CHECK_MSTATUS( status );

        MFloatVector& incandescence = block.inputValue( aIncandescence,  &status ).asFloatVector();
        CHECK_MSTATUS( status );

        float diffuseReflectivity = block.inputValue( aDiffuseReflectivity, &status ).asFloat();
        CHECK_MSTATUS( status );

//      float translucenceCoeff = block.inputValue( aTranslucenceCoeff,
//              &status ).asFloat();
//      CHECK_MSTATUS( status );


        // Get light list
        //
        MArrayDataHandle lightData = block.inputArrayValue( aLightData, &status );
        CHECK_MSTATUS( status );

        int numLights = lightData.elementCount( &status );
        CHECK_MSTATUS( status );


        // Calculate the effect of the lights in the scene on the color
        //

        // Iterate through light list and get ambient/diffuse values
        //
        for( int count=1; count <= numLights; count++ )
        {
            // Get the current light out of the array
            //
            MDataHandle currentLight = lightData.inputValue( &status );
            CHECK_MSTATUS( status );


            // Get the intensity of that light
            //
            MFloatVector& lightIntensity = currentLight.child( aLightIntensity ).asFloatVector();


            // Find ambient component
            //
            if ( currentLight.child( aLightAmbient ).asBool() )
            {
                resultColor += lightIntensity;
            }


            // Find diffuse component
            //
            if ( currentLight.child( aLightDiffuse ).asBool() )
            {
                MFloatVector& lightDirection = currentLight.child( aLightDirection ).asFloatVector();
                float cosln = lightDirection * surfaceNormal;

               if ( cosln > 0.0f ) 
			   {
                    resultColor += lightIntensity * ( cosln * diffuseReflectivity );
               }
            }


            // Advance to the next light.
            //
            if ( count < numLights ) {
                status = lightData.next();
                CHECK_MSTATUS( status );
            }
        }


        // Factor incident light with surface color and add incandescence
        //
        resultColor[0] = resultColor[0] * surfaceColor[0] + incandescence[0];
        resultColor[1] = resultColor[1] * surfaceColor[1] + incandescence[1];
        resultColor[2] = resultColor[2] * surfaceColor[2] + incandescence[2];


        // Set ouput color attribute
        //
		if ( plug == aOutColor || plug.parent() == aOutColor )
        {
            // Get the handle to the attribute
            //
            MDataHandle outColorHandle = block.outputValue( aOutColor, &status );
            CHECK_MSTATUS( status );
            MFloatVector& outColor = outColorHandle.asFloatVector();

            outColor = resultColor;     // Set the output value
            outColorHandle.setClean(); // Mark the output value as clean
        }


        // Set ouput transparency
        //
		if ( plug == aOutTransparency || plug.parent() == aOutTransparency )
        {
            MFloatVector& transparency = block.inputValue( aInTransparency, &status ).asFloatVector();
            CHECK_MSTATUS( status );


            // Get the handle to the attribute
            //
            MDataHandle outTransHandle = block.outputValue( aOutTransparency, &status );
            CHECK_MSTATUS( status );
            MFloatVector& outTrans = outTransHandle.asFloatVector();

            outTrans = transparency;   // Set the output value
            outTransHandle.setClean(); // Mark the output value as clean
        }
    }
    else
    {
        return( MS::kUnknownParameter ); // We got an unexpected plug
    }

    return( MS::kSuccess );
}
Example #4
0
// Load a joint
void skeleton::loadJoint(MDagPath& jointDag,joint* parent)
{
	int i;
	joint newJoint;
	joint* parentJoint = parent;
	if (jointDag.hasFn(MFn::kJoint))
	{
		MFnIkJoint jointFn(jointDag);

		// Get parent index
		int idx=-1;
		if (parent)
		{
			idx = parent->id;
		}
		// Get joint matrix
		MMatrix worldMatrix = jointDag.inclusiveMatrix();
		/*float translation1[3];
		float rotation1[4];
		float scale1[3];
		extractTranMatrix(worldMatrix,translation1,rotation1,scale1);
		Quaternion q(rotation1[0],rotation1[1],rotation1[2],rotation1[3]);
		float angle;
		Vector3 axis;
		q.ToAngleAxis(angle,axis);
		Vector3 x,y,z;
		q.ToAxes(x,y,z);*/
		//printMatrix(worldMatrix);
	
		// Calculate scaling factor inherited by parent
		// Calculate Local Matrix
		MMatrix localMatrix = worldMatrix;
		if (parent)
			localMatrix = worldMatrix * parent->worldMatrix.inverse();
		float translation2[3];
		float rotation2[4];
		float scale2[3];
		extractTranMatrix(worldMatrix,translation2,rotation2,scale2);
		//printMatrix(localMatrix);
	
		// Set joint info
		newJoint.name = jointFn.partialPathName();
		newJoint.id = m_joints.size();
		newJoint.parentIndex = idx;
		newJoint.jointDag = jointDag;
		newJoint.worldMatrix = worldMatrix;
		newJoint.localMatrix = localMatrix;

		for (int iRow = 0; iRow < 4; iRow++)
			for (int iCol = 0; iCol < 3; iCol++)
				newJoint.tran.m_mat[iRow][iCol] = (FLOAT)worldMatrix[iRow][iCol];

		//printMatrix(worldMatrix);

		/*MQuaternion q;
		q = worldMatrix;
		newJoint.tran.q[0] = (float)q.x;
		newJoint.tran.q[1] = (float)q.y;
		newJoint.tran.q[2] = (float)q.z;
		newJoint.tran.q[3] = (float)q.w;
		newJoint.tran.t[0] = (float)worldMatrix[3][0];
		newJoint.tran.t[1] = (float)worldMatrix[3][1];
		newJoint.tran.t[2] = (float)worldMatrix[3][2];*/

		MPlug plug = jointFn.findPlug("unRibbonEnabled");
		if(!plug.isNull())
		{
			bool enabled;
			plug.getValue(enabled);
			if(enabled)
			{
				plug = jointFn.findPlug("unRibbonVisible");
				bool visible;
				plug.getValue(visible);
				plug = jointFn.findPlug("unRibbonAbove");
				float above;
				plug.getValue(above);
				plug = jointFn.findPlug("unRibbonBelow");
				float below;
				plug.getValue(below);
				plug = jointFn.findPlug("unRibbonEdgesPerSecond");
				short edgePerSecond;
				plug.getValue(edgePerSecond);
				plug = jointFn.findPlug("unRibbonEdgeLife");
				float edgeLife;
				plug.getValue(edgeLife);
				plug = jointFn.findPlug("unRibbonGravity");
				float gravity;
				plug.getValue(gravity);
				plug = jointFn.findPlug("unRibbonTextureRows");
				short rows;
				plug.getValue(rows);
				plug = jointFn.findPlug("unRibbonTextureCols");
				short cols;
				plug.getValue(cols);
				plug = jointFn.findPlug("unRibbonTextureSlot");
				short slot;
				plug.getValue(slot);
				plug = jointFn.findPlug("unRibbonVertexColor");
				MObject object;
				plug.getValue(object);
				MFnNumericData data(object);
				float r,g,b;
				data.getData(r,g,b);
				plug = jointFn.findPlug("unRibbonVertexAlpha");
				float alpha;
				plug.getValue(alpha);
				plug = jointFn.findPlug("unRibbonBlendMode");
				short blendMode;
				plug.getValue(blendMode);
				plug = jointFn.findPlug("unRibbonTextureFilename");

				MItDependencyGraph dgIt(plug, MFn::kFileTexture,
					MItDependencyGraph::kUpstream, 
					MItDependencyGraph::kBreadthFirst,
					MItDependencyGraph::kNodeLevel);

				dgIt.disablePruningOnFilter();

				MString textureName;
				if (!dgIt.isDone())
				{
					MObject textureNode = dgIt.thisNode();
					MPlug filenamePlug = MFnDependencyNode(textureNode).findPlug("fileTextureName");
					filenamePlug.getValue(textureName);
				}
				else
				{
					char str[256];
					sprintf(str,"%s ribbon system must has file-texture",newJoint.name.asChar());
					MessageBox(0,str,0,0);
				}

				newJoint.hasRibbonSystem = true;
				newJoint.ribbon.visible = visible;
				newJoint.ribbon.above = above;
				newJoint.ribbon.below = below;
				newJoint.ribbon.gravity = gravity;
				newJoint.ribbon.edgePerSecond = edgePerSecond;
				newJoint.ribbon.edgeLife = edgeLife;
				newJoint.ribbon.rows = rows;
				newJoint.ribbon.cols = cols;
				newJoint.ribbon.slot = slot;
				newJoint.ribbon.color[0] = r;
				newJoint.ribbon.color[1] = g;
				newJoint.ribbon.color[2] = b;
				newJoint.ribbon.alpha = alpha;
				newJoint.ribbon.blendMode = blendMode;
				newJoint.ribbon.textureFilename = textureName.asChar();
			}
		}
		plug = jointFn.findPlug("unParticleEnabled");
		if(!plug.isNull())
		{
			bool enabled;
			plug.getValue(enabled);
			if(enabled)
			{
				newJoint.hasParticleSystem = true;

				plug = jointFn.findPlug("unParticleVisible");
				bool visible;
				plug.getValue(visible);
				plug = jointFn.findPlug("unParticleSpeed");
				float speed;
				plug.getValue(speed);
				plug = jointFn.findPlug("unParticleVariationPercent");
				float variation;
				plug.getValue(variation);
				plug = jointFn.findPlug("unParticleConeAngle");
				float coneAngle;
				plug.getValue(coneAngle);
				plug = jointFn.findPlug("unParticleGravity");
				float gravity;
				plug.getValue(gravity);
				plug = jointFn.findPlug("unParticleExplosiveForce");
				float explosiveForce = 0.0f;
				if(!plug.isNull())
				{
					plug.getValue(explosiveForce);
				}
				plug = jointFn.findPlug("unParticleLife");
				float life;
				plug.getValue(life);
				plug = jointFn.findPlug("unParticleLifeVariation");
				float lifeVar;
				if(plug.isNull())
				{
					lifeVar = 0.0f;
				}
				else
				{
					plug.getValue(lifeVar);
				}
				plug = jointFn.findPlug("unParticleEmissionRate");
				float emissionRate;
				plug.getValue(emissionRate);
				plug = jointFn.findPlug("unParticleLimitNum");
				short limitNum;
				plug.getValue(limitNum);
				plug = jointFn.findPlug("unParticleInitialNum");
				short initialNum = 0;
				if(!plug.isNull())plug.getValue(initialNum);
				plug = jointFn.findPlug("unParticleAttachToEmitter");
				bool attachToEmitter;
				plug.getValue(attachToEmitter);
				plug = jointFn.findPlug("unParticleMoveWithEmitter");
				bool moveWithEmitter = false;
				if(!plug.isNull())plug.getValue(moveWithEmitter);
				//23
				plug = jointFn.findPlug("unParticleForTheSword");
				bool forTheSword = false;
				if(!plug.isNull())plug.getValue(forTheSword);
				//24
				plug = jointFn.findPlug("unParticleForTheSwordInitialAngle");
				float forTheSwordInitialAngle = 0;
				if(!plug.isNull())plug.getValue(forTheSwordInitialAngle);
				//25
				plug = jointFn.findPlug("unParticleWander");
				bool wander = false;
				if(!plug.isNull())plug.getValue(wander);
				//25
				plug = jointFn.findPlug("unParticleWanderRadius");
				float wanderRadius = 0.0f;
				if(!plug.isNull())plug.getValue(wanderRadius);
				//25
				plug = jointFn.findPlug("unParticleWanderSpeed");
				float wanderSpeed = 0.0f;
				if(!plug.isNull())plug.getValue(wanderSpeed);
				plug = jointFn.findPlug("unParticleAspectRatio");
				float aspectRatio;
				if(plug.isNull())
				{
					aspectRatio = 1.0f;
				}
				else
				{
					plug.getValue(aspectRatio);
				}
				plug = jointFn.findPlug("unParticleInitialAngleBegin");
				float angleBegin;
				if(plug.isNull())
				{
					angleBegin = 0.0f;
				}
				else
				{
					plug.getValue(angleBegin);
				}
				plug = jointFn.findPlug("unParticleInitialAngleEnd");
				float angleEnd;
				if(plug.isNull())
				{
					angleEnd = 0.0f;
				}
				else
				{
					plug.getValue(angleEnd);
				}
				plug = jointFn.findPlug("unParticleRotationSpeed");
				float rotationSpeed;
				if(plug.isNull())
				{
					rotationSpeed = 0;
				}
				else
				{
					plug.getValue(rotationSpeed);
				}
				plug = jointFn.findPlug("unParticleRotationSpeedVar");
				float rotationSpeedVar;
				if(plug.isNull())
				{
					rotationSpeedVar = 0;
				}
				else
				{
					plug.getValue(rotationSpeedVar);
				}
				plug = jointFn.findPlug("unParticleEmitterWidth");
				float width;
				plug.getValue(width);
				plug = jointFn.findPlug("unParticleEmitterLength");
				float length;
				plug.getValue(length);
				plug = jointFn.findPlug("unParticleEmitterHeight");
				float height = 0.0f;
				if(!plug.isNull())
				{
					plug.getValue(height);
				}
				plug = jointFn.findPlug("unParticleBlendMode");
				short blendMode;
				plug.getValue(blendMode);
				plug = jointFn.findPlug("unParticleTextureFilename");

				MItDependencyGraph dgIt(plug, MFn::kFileTexture,
					MItDependencyGraph::kUpstream, 
					MItDependencyGraph::kBreadthFirst,
					MItDependencyGraph::kNodeLevel);

				dgIt.disablePruningOnFilter();

				MString textureName;
				if (!dgIt.isDone())
				{
					MObject textureNode = dgIt.thisNode();
					MPlug filenamePlug = MFnDependencyNode(textureNode).findPlug("fileTextureName");
					filenamePlug.getValue(textureName);
				}
				else
				{
					char str[256];
					sprintf(str,"%s particle system must has file-texture",newJoint.name.asChar());
					MessageBox(0,str,0,0);
				}
				plug = jointFn.findPlug("unParticleTextureRows");
				short rows;
				plug.getValue(rows);
				plug = jointFn.findPlug("unParticleTextureCols");
				short cols;
				plug.getValue(cols);
				plug = jointFn.findPlug("unParticleTextureChangeStyle");
				short changeStyle;
				if(plug.isNull())
				{
					//0 - 顺序
					//1 - 随机
					changeStyle = 0;
				}
				else
				{
					plug.getValue(changeStyle);
				}
				plug = jointFn.findPlug("unParticleTextureChangeInterval");
				short changeInterval;
				if(plug.isNull())
				{
					//默认30ms换一个
					changeInterval = 30;
				}
				else
				{
					plug.getValue(changeInterval);
				}
				plug = jointFn.findPlug("unParticleTailLength");
				float tailLength;
				plug.getValue(tailLength);
				plug = jointFn.findPlug("unParticleTimeMiddle");
				float timeMiddle;
				plug.getValue(timeMiddle);
				plug = jointFn.findPlug("unParticleColorStart");
				MObject object;
				plug.getValue(object);
				MFnNumericData dataS(object);
				float colorStart[3];
				dataS.getData(colorStart[0],colorStart[1],colorStart[2]);
				plug = jointFn.findPlug("unParticleColorMiddle");
				plug.getValue(object);
				MFnNumericData dataM(object);
				float colorMiddle[3];
				dataM.getData(colorMiddle[0],colorMiddle[1],colorMiddle[2]);
				plug = jointFn.findPlug("unParticleColorEnd");
				plug.getValue(object);
				MFnNumericData dataE(object);
				float colorEnd[3];
				dataE.getData(colorEnd[0],colorEnd[1],colorEnd[2]);
				plug = jointFn.findPlug("unParticleAlpha");
				plug.getValue(object);
				MFnNumericData dataAlpha(object);
				float alpha[3];
				dataAlpha.getData(alpha[0],alpha[1],alpha[2]);
				//Scale
				plug = jointFn.findPlug("unParticleScale");
				plug.getValue(object);
				MFnNumericData dataScale(object);
				float scale[3];
				dataScale.getData(scale[0],scale[1],scale[2]);
				//ScaleVar
				plug = jointFn.findPlug("unParticleScaleVar");
				float scaleVar[3] = {0.0f,0.0f,0.0f};
				if(!plug.isNull())
				{
					plug.getValue(object);
					MFnNumericData dataScaleVar(object);
					dataScaleVar.getData(scaleVar[0],scaleVar[1],scaleVar[2]);
				}
				//FixedSize
				plug = jointFn.findPlug("unParticleFixedSize");
				bool fixedSize = false;
				if(!plug.isNull())
				{
					plug.getValue(fixedSize);
				}
				//HeadLifeSpan
				plug = jointFn.findPlug("unParticleHeadLifeSpan");
				plug.getValue(object);
				MFnNumericData dataHeadLifeSpan(object);
				short headLifeSpan[3];
				dataHeadLifeSpan.getData(headLifeSpan[0],headLifeSpan[1],headLifeSpan[2]);
				plug = jointFn.findPlug("unParticleHeadDecay");
				plug.getValue(object);
				MFnNumericData dataHeadDecay(object);
				short headDecay[3];
				dataHeadDecay.getData(headDecay[0],headDecay[1],headDecay[2]);
				plug = jointFn.findPlug("unParticleTailLifeSpan");
				plug.getValue(object);
				MFnNumericData dataTailLifeSpan(object);
				short tailLifeSpan[3];
				dataTailLifeSpan.getData(tailLifeSpan[0],tailLifeSpan[1],tailLifeSpan[2]);
				plug = jointFn.findPlug("unParticleTailDecay");
				plug.getValue(object);
				MFnNumericData dataTailDecay(object);
				short tailDecay[3];
				dataTailDecay.getData(tailDecay[0],tailDecay[1],tailDecay[2]);
				plug = jointFn.findPlug("unParticleHead");
				bool head;
				plug.getValue(head);
				plug = jointFn.findPlug("unParticleTail");
				bool tail;
				plug.getValue(tail);
				plug = jointFn.findPlug("unParticleUnShaded");
				bool unshaded;
				plug.getValue(unshaded);
				plug = jointFn.findPlug("unParticleUnFogged");
				bool unfogged;
				plug.getValue(unfogged);
				plug = jointFn.findPlug("unParticleBlockByY0");
				bool blockByY0 = false;
				if(!plug.isNull())
					plug.getValue(blockByY0);

				newJoint.particle.visible = visible;
				newJoint.particle.speed = speed;
				newJoint.particle.variation = variation / 100.0f;
				newJoint.particle.coneAngle = coneAngle;
				newJoint.particle.gravity = gravity;
				newJoint.particle.explosiveForce = explosiveForce;
				newJoint.particle.life = life;
				newJoint.particle.lifeVar = lifeVar;
				newJoint.particle.emissionRate = emissionRate;
				newJoint.particle.initialNum = initialNum;
				newJoint.particle.limitNum = limitNum;
				newJoint.particle.attachToEmitter = attachToEmitter;
				newJoint.particle.moveWithEmitter = moveWithEmitter;
				newJoint.particle.forTheSword = forTheSword;
				newJoint.particle.forTheSwordInitialAngle = forTheSwordInitialAngle;
				newJoint.particle.wander = wander;
				newJoint.particle.wanderRadius = wanderRadius;
				newJoint.particle.wanderSpeed = wanderSpeed;
				newJoint.particle.aspectRatio = aspectRatio;
				newJoint.particle.initialAngleBegin = angleBegin;
				newJoint.particle.initialAngleEnd = angleEnd;
				newJoint.particle.rotationSpeed = rotationSpeed;
				newJoint.particle.rotationSpeedVar = rotationSpeedVar;
				newJoint.particle.width = width;
				newJoint.particle.length = length;
				newJoint.particle.height = height;
				newJoint.particle.blendMode = blendMode;
				newJoint.particle.textureFilename = textureName.asChar();
				newJoint.particle.textureRows = rows;
				newJoint.particle.textureCols = cols;
				newJoint.particle.changeStyle = changeStyle;
				newJoint.particle.changeInterval = changeInterval;
				newJoint.particle.tailLength = tailLength;
				newJoint.particle.timeMiddle = timeMiddle;
				newJoint.particle.colorStart[0] = colorStart[0];
				newJoint.particle.colorStart[1] = colorStart[1];
				newJoint.particle.colorStart[2] = colorStart[2];
				newJoint.particle.colorMiddle[0] = colorMiddle[0];
				newJoint.particle.colorMiddle[1] = colorMiddle[1];
				newJoint.particle.colorMiddle[2] = colorMiddle[2];
				newJoint.particle.colorEnd[0] = colorEnd[0];
				newJoint.particle.colorEnd[1] = colorEnd[1];
				newJoint.particle.colorEnd[2] = colorEnd[2];
				newJoint.particle.alpha[0] = alpha[0];
				newJoint.particle.alpha[1] = alpha[1];
				newJoint.particle.alpha[2] = alpha[2];
				newJoint.particle.scale[0] = scale[0];
				newJoint.particle.scale[1] = scale[1];
				newJoint.particle.scale[2] = scale[2];
				newJoint.particle.scaleVar[0] = scaleVar[0];
				newJoint.particle.scaleVar[1] = scaleVar[1];
				newJoint.particle.scaleVar[2] = scaleVar[2];
				newJoint.particle.fixedSize = fixedSize;
				newJoint.particle.headLifeSpan[0] = headLifeSpan[0];
				newJoint.particle.headLifeSpan[1] = headLifeSpan[1];
				newJoint.particle.headLifeSpan[2] = headLifeSpan[2];
				newJoint.particle.headDecay[0] = headDecay[0];
				newJoint.particle.headDecay[1] = headDecay[1];
				newJoint.particle.headDecay[2] = headDecay[2];
				newJoint.particle.tailLifeSpan[0] = tailLifeSpan[0];
				newJoint.particle.tailLifeSpan[1] = tailLifeSpan[1];
				newJoint.particle.tailLifeSpan[2] = tailLifeSpan[2];
				newJoint.particle.tailDecay[0] = tailDecay[0];
				newJoint.particle.tailDecay[1] = tailDecay[1];
				newJoint.particle.tailDecay[2] = tailDecay[2];
				newJoint.particle.head = head;
				newJoint.particle.tail = tail;
				newJoint.particle.unshaded = unshaded;
				newJoint.particle.unfogged = unfogged;
				newJoint.particle.blockByY0 = blockByY0;
			}
		}

		m_joints.push_back(newJoint);
		// Get pointer to newly created joint
		parentJoint = &newJoint;
	}
	// Load children joints
	for (i=0; i<jointDag.childCount();i++)
	{
		MObject child;
		child = jointDag.child(i);
		MDagPath childDag = jointDag;
		childDag.push(child);
		loadJoint(childDag,parentJoint);
	}

}
MStatus proWater::compute(const MPlug& plug, MDataBlock& dataBlock)
{
    MStatus status = MStatus::kUnknownParameter;
    if (plug.attribute() == outputGeom) {
        // get the input corresponding to this output
        //
        unsigned int index = plug.logicalIndex();
        MObject thisNode = this->thisMObject();
        MPlug inPlug(thisNode,input);
        inPlug.selectAncestorLogicalIndex(index,input);
        MDataHandle hInput = dataBlock.inputValue(inPlug);
        
        // get the input geometry and input groupId
        //
        MDataHandle hGeom = hInput.child(inputGeom);
        MDataHandle hGroup = hInput.child(groupId);
        
        
        
        unsigned int groupId = hGroup.asLong();
        MDataHandle hOutput = dataBlock.outputValue(plug);
        hOutput.copy(hGeom);
        
        
        MStatus returnStatus;
        
        MDataHandle envData = dataBlock.inputValue(envelope, &returnStatus);
        if (MS::kSuccess != returnStatus) return returnStatus;
        float env = envData.asFloat();
        
        MDataHandle timeData = dataBlock.inputValue(time, &returnStatus);
        if(MS::kSuccess != returnStatus) return returnStatus;
        double t = timeData.asDouble();
        
        MDataHandle dirData = dataBlock.inputValue(dir, &returnStatus);
        if(MS::kSuccess != returnStatus) return returnStatus;
        double dirDeg = dirData.asDouble();
        
        MDataHandle bigData = dataBlock.inputValue(bigFreq, &returnStatus);
        if(MS::kSuccess != returnStatus) return returnStatus;
        double bigFreqAmp = bigData.asDouble();
        
        MDataHandle ampData = dataBlock.inputValue(amplitude1, &returnStatus);
        if(MS::kSuccess != returnStatus) return returnStatus;
        double amp1 = ampData.asDouble();
        
        MDataHandle freqData = dataBlock.inputValue(frequency1, &returnStatus);
        if(MS::kSuccess != returnStatus) return returnStatus;
        double freq1 = freqData.asDouble();
        
        MDataHandle ampData2 = dataBlock.inputValue(amplitude2, &returnStatus);
        if(MS::kSuccess != returnStatus) return returnStatus;
        double amp2 = ampData2.asDouble();
        
        MDataHandle freqData2 = dataBlock.inputValue(frequency2, &returnStatus);
        if(MS::kSuccess != returnStatus) return returnStatus;
        double freq2 = freqData2.asDouble();
        
        
        // Get the MFnMesh
        MStatus stat;
        MObject inputObj = hOutput.data();
        MFnMesh * meshFn = new MFnMesh(inputObj, &stat);
        
        // do the deformation
        //
        MItGeometry iter(hOutput,groupId,false);
        
        for ( ; !iter.isDone(); iter.next()) {
            MPoint pt = iter.position();
            
            //float2 uvPoint;
            //float u,v;
            
            //uvPoint[0] = u;
            //uvPoint[1] = v;
            
            //meshFn->getUVAtPoint(pt, uvPoint, MSpace::kObject);
            
            float u = pt.x; //uvPoint[0]*100;
            float v = pt.z; //uvPoint[1]*100;
            
            float degDir = dirDeg;
            
            float dir = degDir* M_PI/180;
            
            float dirX = cos(dir);
            float dirY = sin(dir);
            
            
            float bigFreq = 0.01;
            
            float bigWaves = scaled_raw_noise_3d(0, 1, (u + 3*t*dirX)*bigFreq*dirX, (v + 3*t*dirY)*bigFreq*dirY*2, t*0.01);
            
            
            float frequency1 = freq1/10;//0.2;
            float amplitude1 = amp1;//1.3;
            
            float firstOctave = -(std::abs(scaled_raw_noise_3d(-amplitude1, amplitude1, (float)(u + 0.7*t*dirX)*frequency1*0.4, (float)(v + 0.7*t*dirY)*frequency1*0.6, 0.05*t))-amplitude1);
            
            float frequency2 = freq2/10;
            float amplitude2 = amp2;
        
            float secondOctave = - (std::abs(scaled_raw_noise_3d(-amplitude2, amplitude2, (float)(u + 0.7*t*dirX)*frequency2*0.35, (float)(v + 0.7*t*dirY)*frequency2*0.65, 0.005*t))-amplitude2);
            
            float frequency3 = freq1/10;
            float amplitude3 = amp1/1.5;
            
            float thirdOctave = - (std::abs(scaled_raw_noise_3d(-amplitude3, amplitude3, (float)(u + t*0.5*dirX)*frequency3*0.4, (float)(v + t*0.5*dirY)*frequency3*0.6, 30))-amplitude3);
            
            float frequency4 = freq2/10;
            float amplitude4 = amp2/1.5;
            
            float fourthOctave = scaled_raw_noise_3d(-amplitude4, amplitude4, (float)(u + t*0.5*dirX)*frequency4*0.4, (float)(v + t*0.5*dirY)*frequency4*0.6, 50);
            
            float frequency5 = freq2;
            float amplitude5 = amp2/2;
            
            float fifthOctave = scaled_raw_noise_3d(-amplitude5, amplitude5, (float)(u + t*0.5*dirX)*frequency5*0.15, (float)(v + t*0.5*dirY)*frequency5*0.85, 0.001*t);
            
            float disp = bigFreqAmp*bigWaves + 7*(bigWaves)*firstOctave + secondOctave + thirdOctave*thirdOctave + fourthOctave + std::abs(bigWaves-1)*fifthOctave;
            
            pt = pt + iter.normal()*disp;
            
            iter.setPosition(pt);
        }
        
        delete meshFn;
        status = MStatus::kSuccess;
    }
    
    
    return status;
}
Example #6
0
MBoundingBox cubeLocator::boundingBox () const {
	MPlug plug (thisMObject (), cubeLocator::size) ;
	float multiplier =plug.asFloat () ;
	return (cubeLocator::boundingbox (multiplier)) ;
}
    //---------------------------------------
    void MaterialExporter::setSetParamTexture (
        const cgfxAttrDef* attribute, 
        MObject texture, 
        COLLADASW::Sampler::SamplerType samplerType, 
        COLLADASW::ValueType::ColladaType samplerValueType )
    {
        // Get a pointer to the current stream writer.
        COLLADASW::StreamWriter* streamWriter = mDocumentExporter->getStreamWriter();

        // Get the image id
        MFnDependencyNode textureNode ( texture );
        String plugName = textureNode.name().asChar(); // file1

        // Get the file texture name
        MPlug filenamePlug = textureNode.findPlug ( ATTR_FILE_TEXTURE_NAME );
        MString mayaFileName;
        filenamePlug.getValue ( mayaFileName );
        if ( mayaFileName.length() == 0 ) return;
        String fileName = mayaFileName.asChar ();
        
        // Get the image path
        COLLADASW::URI shaderFxFileUri = getShaderFxFileUri ();

        // Take the filename for the unique image name 
        COLLADASW::URI sourceFileUri ( shaderFxFileUri, fileName );
        if ( sourceFileUri.getScheme ().empty () )
            sourceFileUri.setScheme ( COLLADASW::URI::SCHEME_FILE );
        String mayaImageId = DocumentExporter::mayaNameToColladaName ( sourceFileUri.getPathFileBase().c_str () );

        // Get the image id of the maya image 
        EffectExporter* effectExporter = mDocumentExporter->getEffectExporter ();
        String colladaImageId = effectExporter->findColladaImageId ( mayaImageId );
        if ( colladaImageId.empty () )
        {
            // Check if there is an extra attribute "colladaId" and use this as export id.
            MString attributeValue;
            DagHelper::getPlugValue ( texture, COLLADA_ID_ATTRIBUTE_NAME, attributeValue );
            if ( attributeValue != EMPTY_CSTRING )
            {
                // Generate a valid collada name, if necessary.
                colladaImageId = mDocumentExporter->mayaNameToColladaName ( attributeValue, false );
            }
            else
            {
                // Generate a COLLADA id for the new light object
                colladaImageId = DocumentExporter::mayaNameToColladaName ( textureNode.name() );
            }
            // Make the id unique and store it in a map for refernences.
            EffectTextureExporter* textureExporter = effectExporter->getTextureExporter ();
            colladaImageId = textureExporter->getImageIdList ().addId ( colladaImageId );
            textureExporter->getMayaIdColladaImageId () [mayaImageId] = colladaImageId;
        }

        // Export the image
        EffectTextureExporter* textureExporter = mDocumentExporter->getEffectExporter()->getTextureExporter();
        COLLADASW::Image* colladaImage = textureExporter->exportImage ( mayaImageId, colladaImageId, sourceFileUri );
        mayaImageId = colladaImage->getImageId();

        // Create the sampler and surface sid
        String samplerSid = mayaImageId + COLLADASW::Sampler::SAMPLER_SID_SUFFIX;
        String surfaceSid = mayaImageId + COLLADASW::Sampler::SURFACE_SID_SUFFIX;

        // Avoid export of dublicate sampler params
        if ( mSamplers.find ( samplerSid ) != mSamplers.end () ) return;
        mSamplers.insert ( samplerSid );

        // Create the sampler and add the sampler <setparam>
        COLLADASW::Sampler sampler ( samplerType, samplerSid, surfaceSid );
        sampler.setFormat ( EffectTextureExporter::FORMAT );
        sampler.setImageId ( colladaImage->getImageId() );
        sampler.addInSetParam ( streamWriter );
    }
// Creases, corners, holes are organized by MEL script into maya sets
// that are connected to shape and have corresponded attributes:
// liqSubdivCrease, liqSubdivCorner, liqSubdivHole, liqSubdivStitch
// 'stitch' -- new tag introduced in PRman 11 suited for seamless
// stitching two subdiv surfaces aligned by common edge line.
// If global flag liqglo_useMtorSubdiv is set, then procedure looks also
// for analog mtor attributes
//
void liqRibSubdivisionData::checkExtraTags( MObject &mesh )
{
	CM_TRACE_FUNC("liqRibSubdivisionData::checkExtraTags("<<MFnDependencyNode(mesh).name()<<")");

	MStatus status = MS::kSuccess;
	MPlugArray array;
	MFnMesh    fnMesh( mesh );
	MFnDependencyNode depNode( mesh );
	depNode.getConnections( array ); // collect all plugs connected to mesh

	// this is a temporary solution - the maya2008 polycreases are a bit crap in
	// that they cannot be removed and there is no way at the moment to tag
	// faces as holes in Maya to we keep the "set" way of doing it - Alf
	if( liqglo.liqglo_outputMayaPolyCreases )
	{
		// this looks redundant but there is no other way to determine
		// if the object has creases at all
		MUintArray ids;
		MDoubleArray creaseData;
		status = fnMesh.getCreaseEdges( ids, creaseData );
		if( status == MS::kSuccess )
			addExtraTags( mesh, TAG_CREASE );
		status = fnMesh.getCreaseVertices( ids, creaseData );
		if( status == MS::kSuccess )
			addExtraTags( mesh, TAG_CORNER );
	}

	// for each plug check if it is connected as dst to maya set
	// and this set has attribute for subdiv extra tag with non zero value
	for ( unsigned i = 0 ; i < array.length() ; i++ )
	{
		MPlugArray connections;
		MPlug curPlug = array[i];

		if( !curPlug.connectedTo( connections, false, true ) )
			continue; /* look only for plugs connected as dst (src = false) */

		for ( unsigned i = 0 ; i < connections.length() ; i++ )
		{
			MPlug dstPlug = connections[i];
			MObject dstNode = dstPlug.node();

			if( dstNode.hasFn( MFn::kSet ) )
			{	
				/* if connected to set */
				float extraTagValue;
				MFnDependencyNode setNode( dstNode, &status );
				if( status != MS::kSuccess )
					continue;
				if ( liquidGetPlugValue( setNode, "liqSubdivCrease", extraTagValue, status ) == MS::kSuccess )
        { 
          if( extraTagValue && !liqglo.liqglo_outputMayaPolyCreases ) // skip zero values
            addExtraTags( dstNode, extraTagValue, TAG_CREASE );
        } 
        else 
        if ( liquidGetPlugValue( setNode, "liqSubdivCorner", extraTagValue, status ) == MS::kSuccess )
        { 
          if( extraTagValue && !liqglo.liqglo_outputMayaPolyCreases ) // skip zero values
            addExtraTags( dstNode, extraTagValue, TAG_CORNER );
        }
        else
				if ( liquidGetPlugValue( setNode, "liqSubdivHole", extraTagValue, status ) == MS::kSuccess )
        { 
          if( extraTagValue ) // skip zero values
            addExtraTags( dstNode, extraTagValue, TAG_HOLE );
        }
				else
        if ( liquidGetPlugValue( setNode, "liqSubdivStitch", extraTagValue, status ) == MS::kSuccess )
        { 
          if( extraTagValue ) // skip zero values
            addExtraTags( dstNode, extraTagValue, TAG_STITCH );
        }
        
				if( liqglo.liqglo_useMtorSubdiv ) // check mtor subdivisions extra tag
				{
					if ( liquidGetPlugValue( setNode, "mtorSubdivCrease", extraTagValue, status ) == MS::kSuccess )
          { 
            if( extraTagValue && !liqglo.liqglo_outputMayaPolyCreases ) // skip zero values
              addExtraTags( dstNode, extraTagValue, TAG_CREASE );
          } 
          else 
					if ( liquidGetPlugValue( setNode, "mtorSubdivCorner", extraTagValue, status ) == MS::kSuccess )
          { 
            if( extraTagValue && !liqglo.liqglo_outputMayaPolyCreases ) // skip zero values
              addExtraTags( dstNode, extraTagValue, TAG_CORNER );
          } 
          else 
          if ( liquidGetPlugValue( setNode, "mtorSubdivHole", extraTagValue, status ) == MS::kSuccess )
          { 
            if( extraTagValue ) // skip zero values
              addExtraTags( dstNode, extraTagValue, TAG_HOLE );
          }
        }
			}
		}
	}
	bool interpolateBoundaryOld = false;
  bool mtor_interpolateBoundary = false;
  int liqSubdivUVInterpolation;
  liquidGetPlugValue( fnMesh, "liqSubdivInterpolateBoundary", interpolateBoundary, status );
  liquidGetPlugValue( fnMesh, "interpBoundary", interpolateBoundaryOld, status );
	
	if( liqglo.liqglo_useMtorSubdiv )
    liquidGetPlugValue( fnMesh, "mtorSubdivInterp", mtor_interpolateBoundary, status );
 
  if ( liquidGetPlugValue( fnMesh, "liqSubdivUVInterpolation", liqSubdivUVInterpolation, status ) == MS::kSuccess )
	{
		switch( liqSubdivUVInterpolation )
		{
			case 0: // true facevarying
			  trueFacevarying = true;
			case 1: //
			  uvDetail = rFaceVarying;
        break;
			case 2:
			  uvDetail = rFaceVertex;
        break;
		}
	}

	if( mtor_interpolateBoundary || interpolateBoundaryOld )
		interpolateBoundary = 2; // Old School

	if( interpolateBoundary )
		addExtraTags( mesh, interpolateBoundary, TAG_BOUNDARY );

	if( trueFacevarying )
		addExtraTags( mesh, 0, TAG_FACEVARYINGBOUNDARY );
}
Example #9
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;
}
Example #10
0
MStatus OnbShader::compute(const MPlug& plug, MDataBlock& block)
{
	// Sanity check
	if (plug != aOutColor && plug.parent() != aOutColor &&
		plug != aOutTransparency && plug.parent() != aOutTransparency)
	{
		return MS::kUnknownParameter;
	}

	// Note that this currently only implements the diffuse portion of the
	// shader and ignores specular. The diffuse portion is the Oren-Nayar
	// computation from:
	//   Engel, Wolfgang et al. Programming Vertex, Geometry, and Pixel Shaders
	//   http://content.gpwiki.org/index.php/D3DBook:(Lighting)_Oren-Nayar
	// Further extensions could be added to this compute method to include
	// the intended Blinn specular component as well as ambient and
	// incandescence components.
	// See the VP2 fragment-based implementation in onbShaderOverride for the
	// full shader.
	MStatus status;
	MFloatVector resultColor(0.0f, 0.0f, 0.0f);
	MFloatVector resultTransparency(0.0f, 0.0f, 0.0f);

	// Get surface shading parameters from input block
	const MFloatVector& surfaceColor =
		block.inputValue(aColor, &status).asFloatVector();
	CHECK_MSTATUS(status);
	const float roughness = block.inputValue(aRoughness, &status).asFloat();
	CHECK_MSTATUS(status);
	const MFloatVector& transparency =
		block.inputValue(aTransparency, &status).asFloatVector();
	CHECK_MSTATUS(status);
	const MFloatVector& surfaceNormal =
		block.inputValue(aNormalCamera, &status).asFloatVector();
	CHECK_MSTATUS(status);
	const MFloatVector& rayDirection =
		block.inputValue(aRayDirection).asFloatVector();
	const MFloatVector viewDirection = -rayDirection;

	// Pre-compute some values that do not vary with lights
	const float NV = viewDirection*surfaceNormal;
	const float acosNV = acosf(NV);
	const float roughnessSq = roughness*roughness;
	const float A = 1.0f - 0.5f*(roughnessSq/(roughnessSq + 0.57f));
	const float B = 0.45f*(roughnessSq/(roughnessSq + 0.09f));

	// Get light list
	MArrayDataHandle lightData = block.inputArrayValue(aLightData, &status);
	CHECK_MSTATUS(status);
	const int numLights = lightData.elementCount(&status);
	CHECK_MSTATUS(status);

	// Iterate through light list and get ambient/diffuse values
	for (int count=1; count<=numLights; count++)
	{
		// Get the current light
		MDataHandle currentLight = lightData.inputValue(&status);
		CHECK_MSTATUS(status);

		// Find diffuse component
		if (currentLight.child(aLightDiffuse).asBool())
		{
			// Get the intensity and direction of that light
			const MFloatVector& lightIntensity =
				currentLight.child(aLightIntensity).asFloatVector();
			const MFloatVector& lightDirection =
				currentLight.child(aLightDirection).asFloatVector();

			// Compute the diffuse factor
			const float NL = lightDirection*surfaceNormal;
			const float acosNL = acosf(NL);
			const float alpha = std::max(acosNV, acosNL);
			const float beta = std::min(acosNV, acosNL);
			const float gamma =
				(viewDirection - (surfaceNormal*NV)) *
				(lightDirection - (surfaceNormal*NL));
			const float C = sinf(alpha)*tanf(beta);
			const float factor =
				std::max(0.0f, NL)*(A + B*std::max(0.0f, gamma)*C);

			// Add to result color
			resultColor += lightIntensity*factor;
		}

		// Advance to the next light.
		if (count < numLights)
		{
			status = lightData.next();
			CHECK_MSTATUS(status);
		}
	}

	// Factor incident light with surface color
	resultColor[0] = resultColor[0]*surfaceColor[0];
	resultColor[1] = resultColor[1]*surfaceColor[1];
	resultColor[2] = resultColor[2]*surfaceColor[2];

	// Set ouput color attribute
	if (plug == aOutColor || plug.parent() == aOutColor)
	{
		// Get the handle to the attribute
		MDataHandle outColorHandle = block.outputValue(aOutColor, &status);
		CHECK_MSTATUS(status);
		MFloatVector& outColor = outColorHandle.asFloatVector();

		// Set the result and mark it clean
		outColor = resultColor;
		outColorHandle.setClean();
	}

	// Set ouput transparency
	if (plug == aOutTransparency || plug.parent() == aOutTransparency)
	{
		// Get the handle to the attribute
		MDataHandle outTransHandle =
			block.outputValue(aOutTransparency, &status);
		CHECK_MSTATUS(status);
		MFloatVector& outTrans = outTransHandle.asFloatVector();

		// Set the result and mark it clean
		outTrans = transparency;
		outTransHandle.setClean();
	}

	return MS::kSuccess;
}
Example #11
0
MStatus splatDeformer::compute(const MPlug& plug, MDataBlock& data)
{
	// do this if we are using an OpenMP implementation that is not the same as Maya's.
	// Even if it is the same, it does no harm to make this call.
	MThreadUtils::syncNumOpenMPThreads();

	MStatus status = MStatus::kUnknownParameter;
 	if (plug.attribute() != outputGeom) {
		return status;
	}

	unsigned int index = plug.logicalIndex();
	MObject thisNode = this->thisMObject();

	// get input value
	MPlug inPlug(thisNode,input);
	inPlug.selectAncestorLogicalIndex(index,input);
	MDataHandle hInput = data.inputValue(inPlug, &status);
	MCheckStatus(status, "ERROR getting input mesh\n");
	
	// get the input geometry
	MDataHandle inputData = hInput.child(inputGeom);
	if (inputData.type() != MFnData::kMesh) {
 		printf("Incorrect input geometry type\n");
		return MStatus::kFailure;
 	}

	// get the input groupId - ignored for now...
	MDataHandle hGroup = inputData.child(groupId);
	unsigned int groupId = hGroup.asLong();

	// get deforming mesh
	MDataHandle deformData = data.inputValue(deformingMesh, &status);
	MCheckStatus(status, "ERROR getting deforming mesh\n");
    if (deformData.type() != MFnData::kMesh) {
		printf("Incorrect deformer geometry type %d\n", deformData.type());
		return MStatus::kFailure;
	}

  	MObject dSurf = deformData.asMeshTransformed();
 	MFnMesh fnDeformingMesh;
 	fnDeformingMesh.setObject( dSurf ) ;

	MDataHandle outputData = data.outputValue(plug);
	outputData.copy(inputData);
 	if (outputData.type() != MFnData::kMesh) {
		printf("Incorrect output mesh type\n");
		return MStatus::kFailure;
	}
	
	MItGeometry iter(outputData, groupId, false);

	// create fast intersector structure
	MMeshIntersector intersector;
	intersector.create(dSurf);

	// get all points at once. Faster to query, and also better for
	// threading than using iterator
	MPointArray verts;
	iter.allPositions(verts);
	int nPoints = verts.length();

	// use bool variable as lightweight object for failure check in loop below
	bool failed = false;

 	MTimer timer; timer.beginTimer();

#ifdef _OPENMP
#pragma omp parallel for
#endif
 	for(int i=0; i<nPoints; i++) {

		// Cannot break out of an OpenMP loop, so if one of the
		// intersections failed, skip the rest
		if(failed) continue;

		// mesh point object must be in loop-local scope to avoid race conditions
		MPointOnMesh meshPoint;

		// Do intersection. Need to use per-thread status value as
		// MStatus has internal state and may trigger race conditions
		// if set from multiple threads. Probably benign in this case,
		// but worth being careful.
		MStatus localStatus = intersector.getClosestPoint(verts[i], meshPoint);
		if(localStatus != MStatus::kSuccess) {
			// NOTE - we cannot break out of an OpenMP region, so set
			// bad status and skip remaining iterations
			failed = true;
			continue;
		}

		// default OpenMP scheduling breaks traversal into large
		// chunks, so low risk of false sharing here in array write.
		verts[i] = meshPoint.getPoint();
 	}

 	timer.endTimer(); printf("Runtime for threaded loop %f\n", timer.elapsedTime());

	// write values back onto output using fast set method on iterator
	iter.setAllPositions(verts);

	if(failed) {
		printf("Closest point failed\n");
		return MStatus::kFailure;
	}

	return status;
}
Example #12
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);
		}
	}
}
Example #13
0
void MG_vectorGL::draw( M3dView & view, const MDagPath & path, 
							 M3dView::DisplayStyle dispStyle,
							 M3dView::DisplayStatus status )
{ 
   
	MPlug drawItP (thisMObject(),drawIt);
	bool drawItV;
	drawItP.getValue(drawItV);
	
	
	MPlug arrowSizeP (thisMObject(),arrowSize);
	double arrowSizeV;
	arrowSizeP.getValue(arrowSizeV);
	
	MPlug upVecP (thisMObject(),upVec);
	MVector upVecV;
	upVecP.child(0).getValue(upVecV.x);
	upVecP.child(1).getValue(upVecV.y);
	upVecP.child(2).getValue(upVecV.z);
	
	MPlug vecsP (thisMObject(),vecs);
	MPlug startPointP (thisMObject(),startPoint);

	 
	int elemVecs   =  vecsP.numElements();
	int elemPoints =  startPointP.numElements();
	
	if ( drawItV == 0 )
	{
	  return ;
	  
	}
	
	if (elemVecs != elemPoints )
	{
	  return;
	  
	}
	
	
	// Draw it 
	view.beginGL();
	glPushAttrib( GL_ALL_ATTRIB_BITS );
	glEnable(GL_BLEND);
	glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
	glLineWidth(2);
	if(status == M3dView::kLead)
		glColor4f(0.0,1.0,0.0,1.0f);
	else
		glColor4f(1.0,1.0,0.0,1.0f);
	
	for ( unsigned int i = 0 ; i < elemVecs ; i++ )
	{
	   vecsP.selectAncestorLogicalIndex( i , vecs);
	   startPointP.selectAncestorLogicalIndex( i , startPoint);

	
	   MVector currentVec ;
	   MPoint currentPoint;
	  
	  vecsP.child(0).getValue(currentVec.x);
	  vecsP.child(1).getValue(currentVec.y);
	  vecsP.child(2).getValue(currentVec.z);
	  
	  startPointP.child(0).getValue(currentPoint.x);
	  startPointP.child(1).getValue(currentPoint.y);
	  startPointP.child(2).getValue(currentPoint.z);
	    
	  drawArrow(currentVec , upVecV , arrowSizeV , currentPoint);
	  

	}


	glDisable(GL_BLEND);
	glPopAttrib();



}
Example #14
0
void NifMeshExporterSkyrim::ExportMesh( MObject dagNode ) {
	//out << "NifTranslator::ExportMesh {";
	ComplexShape cs;
	MStatus stat;
	MObject mesh;

	//Find Mesh child of given transform object
	MFnDagNode nodeFn(dagNode);

	cs.SetName(this->translatorUtils->MakeNifName(nodeFn.name()));


	for (int i = 0; i != nodeFn.childCount(); ++i) {
		// get a handle to the child
		if (nodeFn.child(i).hasFn(MFn::kMesh)) {
			MFnMesh tempFn(nodeFn.child(i));
			//No history items
			if (!tempFn.isIntermediateObject()) {
				//out << "Found a mesh child." << endl;
				mesh = nodeFn.child(i);
				break;
			}
		}
	}

	MFnMesh visibleMeshFn(mesh, &stat);
	if (stat != MS::kSuccess) {
		//out << stat.errorString().asChar() << endl;
		throw runtime_error("Failed to create visibleMeshFn.");
	}

	//out << visibleMeshFn.name().asChar() << ") {" << endl;
	MFnMesh meshFn;
	MObject dataObj;
	MPlugArray inMeshPlugArray;
	MPlug childPlug;
	MPlug geomPlug;
	MPlug inputPlug;

	// this will hold the returned vertex positions
	MPointArray vts;

	//For now always use the visible mesh
	meshFn.setObject(mesh);

	//out << "Use the function set to get the points" << endl;
	// use the function set to get the points
	stat = meshFn.getPoints(vts);
	if (stat != MS::kSuccess) {
		//out << stat.errorString().asChar() << endl;
		throw runtime_error("Failed to get points.");
	}

	//Maya won't store any information about objects with no vertices.  Just skip it.
	if (vts.length() == 0) {
		MGlobal::displayWarning("An object in this scene has no vertices.  Nothing will be exported.");
		return;
	}

	vector<WeightedVertex> nif_vts(vts.length());
	for (int i = 0; i != vts.length(); ++i) {
		nif_vts[i].position.x = float(vts[i].x);
		nif_vts[i].position.y = float(vts[i].y);
		nif_vts[i].position.z = float(vts[i].z);
	}

	//Set vertex info later since it includes skin weights
	//cs.SetVertices( nif_vts );

	//out << "Use the function set to get the colors" << endl;
	MColorArray myColors;
	meshFn.getFaceVertexColors(myColors);

	//out << "Prepare NIF color vector" << endl;
	vector<Color4> niColors(myColors.length());
	for (unsigned int i = 0; i < myColors.length(); ++i) {
		niColors[i] = Color4(myColors[i].r, myColors[i].g, myColors[i].b, myColors[i].a);
	}
	cs.SetColors(niColors);


	// this will hold the returned vertex positions
	MFloatVectorArray nmls;

	//out << "Use the function set to get the normals" << endl;
	// use the function set to get the normals
	stat = meshFn.getNormals(nmls, MSpace::kTransform);
	if (stat != MS::kSuccess) {
		//out << stat.errorString().asChar() << endl;
		throw runtime_error("Failed to get normals");
	}

	//out << "Prepare NIF normal vector" << endl;
	vector<Vector3> nif_nmls(nmls.length());
	for (int i = 0; i != nmls.length(); ++i) {
		nif_nmls[i].x = float(nmls[i].x);
		nif_nmls[i].y = float(nmls[i].y);
		nif_nmls[i].z = float(nmls[i].z);
	}
	cs.SetNormals(nif_nmls);

	//out << "Use the function set to get the UV set names" << endl;
	MStringArray uvSetNames;
	MString baseUVSet;
	MFloatArray myUCoords;
	MFloatArray myVCoords;
	bool has_uvs = false;

	// get the names of the uv sets on the mesh
	meshFn.getUVSetNames(uvSetNames);

	vector<TexCoordSet> nif_uvs;

	//Record assotiation between name and uv set index for later
	map<string, int> uvSetNums;

	int set_num = 0;
	for (unsigned int i = 0; i < uvSetNames.length(); ++i) {
		if (meshFn.numUVs(uvSetNames[i]) > 0) {
			TexType tt;
			string set_name = uvSetNames[i].asChar();
			if (set_name == "base" || set_name == "map1") {
				tt = BASE_MAP;
			}
			else if (set_name == "dark") {
				tt = DARK_MAP;
			}
			else if (set_name == "detail") {
				tt = DETAIL_MAP;
			}
			else if (set_name == "gloss") {
				tt = GLOSS_MAP;
			}
			else if (set_name == "glow") {
				tt = GLOW_MAP;
			}
			else if (set_name == "bump") {
				tt = BUMP_MAP;
			}
			else if (set_name == "decal0") {
				tt = DECAL_0_MAP;
			}
			else if (set_name == "decal1") {
				tt = DECAL_1_MAP;
			}
			else {
				tt = BASE_MAP;
			}

			//Record the assotiation
			uvSetNums[set_name] = set_num;

			//Get the UVs
			meshFn.getUVs(myUCoords, myVCoords, &uvSetNames[i]);

			//Make sure this set actually has some UVs in it.  Maya sometimes returns empty UV sets.
			if (myUCoords.length() == 0) {
				continue;
			}

			//Store the data
			TexCoordSet tcs;
			tcs.texType = tt;
			tcs.texCoords.resize(myUCoords.length());
			for (unsigned int j = 0; j < myUCoords.length(); ++j) {
				tcs.texCoords[j].u = myUCoords[j];
				//Flip the V coords
				tcs.texCoords[j].v = 1.0f - myVCoords[j];
			}
			nif_uvs.push_back(tcs);

			baseUVSet = uvSetNames[i];
			has_uvs = true;

			set_num++;
		}
	}

	cs.SetTexCoordSets(nif_uvs);

	// this will hold references to the shaders used on the meshes
	MObjectArray Shaders;

	// this is used to hold indices to the materials returned in the object array
	MIntArray    FaceIndices;

	//out << "Get the connected shaders" << endl;
	// get the shaders used by the i'th mesh instance
	// Assume this is not instanced for now
	// TODO support instancing properly
	stat = visibleMeshFn.getConnectedShaders(0, Shaders, FaceIndices);

	if (stat != MS::kSuccess) {
		//out << stat.errorString().asChar() << endl;
		throw runtime_error("Failed to get connected shader list.");

	}

	vector<ComplexFace> nif_faces;


	//Add shaders to propGroup array
	vector< vector<NiPropertyRef> > propGroups;
	for (unsigned int shader_num = 0; shader_num < Shaders.length(); ++shader_num) {

		//Maya sometimes lists shaders that are not actually attached to any face.  Disregard them.
		bool shader_is_used = false;
		for (size_t f = 0; f < FaceIndices.length(); ++f) {
			if (FaceIndices[f] == shader_num) {
				shader_is_used = true;
				break;
			}
		}

		if (shader_is_used == false) {
			//Shader isn't actually used, so continue to the next one.
			continue;
		}

		//out << "Found attached shader:  ";
		//Attach all properties previously associated with this shader to
		//this NiTriShape
		MFnDependencyNode fnDep(Shaders[shader_num]);

		//Find the shader that this shading group connects to
		MPlug p = fnDep.findPlug("surfaceShader");
		MPlugArray plugs;
		p.connectedTo(plugs, true, false);
		for (unsigned int i = 0; i < plugs.length(); ++i) {
			if (plugs[i].node().hasFn(MFn::kLambert)) {
				fnDep.setObject(plugs[i].node());
				break;
			}
		}

		//out << fnDep.name().asChar() << endl;
		vector<NiPropertyRef> niProps = this->translatorData->shaders[fnDep.name().asChar()];

		propGroups.push_back(niProps);
	}
	cs.SetPropGroups(propGroups);

	//out << "Export vertex and normal data" << endl;
	// attach an iterator to the mesh
	MItMeshPolygon itPoly(mesh, &stat);
	if (stat != MS::kSuccess) {
		throw runtime_error("Failed to create polygon iterator.");
	}

	// Create a list of faces with vertex IDs, and duplicate normals so they have the same ID
	for (; !itPoly.isDone(); itPoly.next()) {
		int poly_vert_count = itPoly.polygonVertexCount(&stat);

		if (stat != MS::kSuccess) {
			throw runtime_error("Failed to get vertex count.");
		}

		//Ignore polygons with less than 3 vertices
		if (poly_vert_count < 3) {
			continue;
		}

		ComplexFace cf;

		//Assume all faces use material 0 for now
		cf.propGroupIndex = 0;

		for (int i = 0; i < poly_vert_count; ++i) {
			ComplexPoint cp;

			cp.vertexIndex = itPoly.vertexIndex(i);
			cp.normalIndex = itPoly.normalIndex(i);
			if (niColors.size() > 0) {
				int color_index;
				stat = meshFn.getFaceVertexColorIndex(itPoly.index(), i, color_index);
				if (stat != MS::kSuccess) {
					//out << stat.errorString().asChar() << endl;
					throw runtime_error("Failed to get vertex color.");
				}
				cp.colorIndex = color_index;
			}

			//Get the UV set names used by this particular vertex
			MStringArray vertUvSetNames;
			itPoly.getUVSetNames(vertUvSetNames);
			for (unsigned int j = 0; j < vertUvSetNames.length(); ++j) {
				TexCoordIndex tci;
				tci.texCoordSetIndex = uvSetNums[vertUvSetNames[j].asChar()];
				int uv_index;
				itPoly.getUVIndex(i, uv_index, &vertUvSetNames[j]);
				tci.texCoordIndex = uv_index;
				cp.texCoordIndices.push_back(tci);
			}
			cf.points.push_back(cp);
		}
		nif_faces.push_back(cf);
	}

	//Set shader/face association
	if (nif_faces.size() != FaceIndices.length()) {
		throw runtime_error("Num faces found do not match num faces reported.");
	}
	for (unsigned int face_index = 0; face_index < nif_faces.size(); ++face_index) {
		nif_faces[face_index].propGroupIndex = FaceIndices[face_index];
	}

	cs.SetFaces(nif_faces);

	//--Skin Processing--//

	//Look up any skin clusters
	if (this->translatorData->meshClusters.find(visibleMeshFn.fullPathName().asChar()) != this->translatorData->meshClusters.end()) {
		const vector<MObject> & clusters = this->translatorData->meshClusters[visibleMeshFn.fullPathName().asChar()];
		if (clusters.size() > 1) {
			throw runtime_error("Objects with multiple skin clusters affecting them are not currently supported.  Try deleting the history and re-binding them.");
		}

		vector<MObject>::const_iterator cluster = clusters.begin();
		if (cluster->isNull() != true) {
			MFnSkinCluster clusterFn(*cluster);


			//out << "Processing skin..." << endl;
			//Get path to visible mesh
			MDagPath meshPath;
			visibleMeshFn.getPath(meshPath);

			//out << "Getting a list of all verticies in this mesh" << endl;
			//Get a list of all vertices in this mesh
			MFnSingleIndexedComponent compFn;
			MObject vertices = compFn.create(MFn::kMeshVertComponent);
			MItGeometry gIt(meshPath);
			MIntArray vertex_indices(gIt.count());
			for (int vert_index = 0; vert_index < gIt.count(); ++vert_index) {
				vertex_indices[vert_index] = vert_index;
			}
			compFn.addElements(vertex_indices);

			//out << "Getting Influences" << endl;
			//Get influences
			MDagPathArray myBones;
			clusterFn.influenceObjects(myBones, &stat);

			//out << "Creating a list of NiNodeRefs of influences." << endl;
			//Create list of NiNodeRefs of influences
			vector<NiNodeRef> niBones(myBones.length());
			for (unsigned int bone_index = 0; bone_index < niBones.size(); ++bone_index) {
				const char* boneName = myBones[bone_index].fullPathName().asChar();
				if (this->translatorData->nodes.find(myBones[bone_index].fullPathName().asChar()) == this->translatorData->nodes.end()) {
					//There is a problem; one of the joints was not exported.  Abort.
					throw runtime_error("One of the joints necessary to export a bound skin was not exported.");
				}
				niBones[bone_index] = this->translatorData->nodes[myBones[bone_index].fullPathName().asChar()];
			}

			//out << "Getting weights from Maya" << endl;
			//Get weights from Maya
			MDoubleArray myWeights;
			unsigned int bone_count = myBones.length();
			stat = clusterFn.getWeights(meshPath, vertices, myWeights, bone_count);
			if (stat != MS::kSuccess) {
				//out << stat.errorString().asChar() << endl;
				throw runtime_error("Failed to get vertex weights.");
			}

			//out << "Setting skin influence list in ComplexShape" << endl;
			//Set skin information in ComplexShape
			cs.SetSkinInfluences(niBones);

			//out << "Adding weights to ComplexShape vertices" << endl;
			//out << "Number of weights:  " << myWeights.length() << endl;
			//out << "Number of bones:  " << myBones.length() << endl;
			//out << "Number of Maya vertices:  " << gIt.count() << endl;
			//out << "Number of NIF vertices:  " << int(nif_vts.size()) << endl;
			unsigned int weight_index = 0;
			SkinInfluence sk;
			for (unsigned int vert_index = 0; vert_index < nif_vts.size(); ++vert_index) {
				for (unsigned int bone_index = 0; bone_index < myBones.length(); ++bone_index) {
					//out << "vert_index:  " << vert_index << "  bone_index:  " << bone_index << "  weight_index:  " << weight_index << endl;	
					// Only bother with weights that are significant
					if (myWeights[weight_index] > 0.0f) {
						sk.influenceIndex = bone_index;
						sk.weight = float(myWeights[weight_index]);

						nif_vts[vert_index].weights.push_back(sk);
					}
					++weight_index;
				}
			}
		}

		MPlugArray connected_dismember_plugs;
		MObjectArray dismember_nodes;
		meshFn.findPlug("message").connectedTo(connected_dismember_plugs, false, true);

		bool has_valid_dismemember_partitions = true;
		int faces_count = cs.GetFaces().size();
		int current_face_index;
		vector<BodyPartList> body_parts_list;
		vector<uint> dismember_faces(faces_count, 0);

		for (int x = 0; x < connected_dismember_plugs.length(); x++) {
			MFnDependencyNode dependency_node(connected_dismember_plugs[x].node());
			if (dependency_node.typeName() == "nifDismemberPartition") {
				dismember_nodes.append(dependency_node.object());
			}
		}

		if (dismember_nodes.length() == 0) {
			has_valid_dismemember_partitions = false;
		}
		else {
			int blind_data_id;
			int blind_data_value;
			MStatus status;
			MPlug target_faces_plug;
			MItMeshPolygon it_polygons(meshFn.object());
			MString mel_command;
			MStringArray current_body_parts_flags;
			MFnDependencyNode current_dismember_node;
			MFnDependencyNode current_blind_data_node;

			//Naive sort here, there is no reason and is extremely undesirable and not recommended to have more
			//than 10-20 dismember partitions out of many reasons, so it's okay here
			//as it makes the code easier to understand
			vector<int> dismember_nodes_id(dismember_nodes.length(), -1);
			for (int x = 0; x < dismember_nodes.length(); x++) {
				current_dismember_node.setObject(dismember_nodes[x]);
				connected_dismember_plugs.clear();
				current_dismember_node.findPlug("targetFaces").connectedTo(connected_dismember_plugs, true, false);
				if (connected_dismember_plugs.length() == 0) {
					has_valid_dismemember_partitions = false;
					break;
				}
				current_blind_data_node.setObject(connected_dismember_plugs[0].node());
				dismember_nodes_id[x] = current_blind_data_node.findPlug("typeId").asInt();
			}
			for (int x = 0; x < dismember_nodes.length() - 1; x++) {
				for (int y = x + 1; y < dismember_nodes.length(); y++) {
					if (dismember_nodes_id[x] > dismember_nodes_id[y]) {
						MObject aux = dismember_nodes[x];
						blind_data_id = dismember_nodes_id[x];
						dismember_nodes[x] = dismember_nodes[y];
						dismember_nodes_id[x] = dismember_nodes_id[y];
						dismember_nodes[y] = aux;
						dismember_nodes_id[y] = blind_data_id;
					}
				}
			}

			for (int x = 0; x < dismember_nodes.length(); x++) {
				current_dismember_node.setObject(dismember_nodes[x]);
				target_faces_plug = current_dismember_node.findPlug("targetFaces");
				connected_dismember_plugs.clear();
				target_faces_plug.connectedTo(connected_dismember_plugs, true, false);
				if (connected_dismember_plugs.length() > 0) {
					current_blind_data_node.setObject(connected_dismember_plugs[0].node());
					current_face_index = 0;
					blind_data_id = current_blind_data_node.findPlug("typeId").asInt();
					for (it_polygons.reset(); !it_polygons.isDone(); it_polygons.next()) {
						if (it_polygons.polygonVertexCount() >= 3) {
							status = meshFn.getIntBlindData(it_polygons.index(), MFn::Type::kMeshPolygonComponent, blind_data_id, "dismemberValue", blind_data_value);
							if (status == MStatus::kSuccess && blind_data_value == 1 &&
								meshFn.hasBlindDataComponentId(it_polygons.index(), MFn::Type::kMeshPolygonComponent, blind_data_id)) {
								dismember_faces[current_face_index] = x;
							}
							current_face_index++;
						}
					}
				}
				else {
					has_valid_dismemember_partitions = false;
					break;
				}

				mel_command = "getAttr ";
				mel_command += current_dismember_node.name();
				mel_command += ".bodyPartsFlags";
				status = MGlobal::executeCommand(mel_command, current_body_parts_flags);
				BSDismemberBodyPartType body_part_type = NifDismemberPartition::stringArrayToBodyPartType(current_body_parts_flags);
				current_body_parts_flags.clear();

				mel_command = "getAttr ";
				mel_command += current_dismember_node.name();
				mel_command += ".partsFlags";
				status = MGlobal::executeCommand(mel_command, current_body_parts_flags);
				BSPartFlag part_type = NifDismemberPartition::stringArrayToPart(current_body_parts_flags);
				current_body_parts_flags.clear();

				BodyPartList body_part;
				body_part.bodyPart = body_part_type;
				body_part.partFlag = part_type;
				body_parts_list.push_back(body_part);
			}
		}

		if (has_valid_dismemember_partitions == false) {
			MGlobal::displayWarning("No proper dismember partitions, generating default ones for " + meshFn.name());

			for (int x = 0; x < dismember_faces.size(); x++) {
				dismember_faces[x] = 0;
			}

			BodyPartList body_part;
			body_part.bodyPart = (BSDismemberBodyPartType)0;
			body_part.partFlag = (BSPartFlag)(PF_EDITOR_VISIBLE | PF_START_NET_BONESET);
			body_parts_list.clear();
			body_parts_list.push_back(body_part);
		}

		cs.SetDismemberPartitionsBodyParts(body_parts_list);
		cs.SetDismemberPartitionsFaces(dismember_faces);
	}

	//out << "Setting vertex info" << endl;
	//Set vertex info now that any skins have been processed
	cs.SetVertices(nif_vts);

	//ComplexShape is now complete, so split it

	//Get parent
	NiNodeRef parNode = this->translatorUtils->GetDAGParent(dagNode);
	Matrix44 transform = Matrix44::IDENTITY;
	vector<NiNodeRef> influences = cs.GetSkinInfluences();
	if (influences.size() > 0) {
		//This is a skin, so we use the common ancestor of all influences
		//as the parent
		vector<NiAVObjectRef> objects;
		for (size_t i = 0; i < influences.size(); ++i) {
			objects.push_back(StaticCast<NiAVObject>(influences[i]));
		}

		//Get world transform of existing parent
		Matrix44 oldParWorld = parNode->GetWorldTransform();

		//Set new parent node
		parNode = FindCommonAncestor(objects);

		transform = oldParWorld * parNode->GetWorldTransform().Inverse();
	}

	//Get transform using temporary NiAVObject
	NiAVObjectRef tempAV = new NiAVObject;
	this->nodeExporter->ExportAV(tempAV, dagNode);

	NiAVObjectRef avObj;
	if (this->translatorOptions->exportTangentSpace == "falloutskyrimtangentspace") {
		//out << "Split ComplexShape from " << meshFn.name().asChar() << endl;
		avObj = cs.Split(parNode, tempAV->GetLocalTransform() * transform, this->translatorOptions->exportBonesPerSkinPartition,
			this->translatorOptions->exportAsTriStrips, true, this->translatorOptions->exportMinimumVertexWeight, 16);
	}
	else {
		avObj = cs.Split(parNode, tempAV->GetLocalTransform() * transform, this->translatorOptions->exportBonesPerSkinPartition,
			this->translatorOptions->exportAsTriStrips, false, this->translatorOptions->exportMinimumVertexWeight);
	}


	//out << "Get the NiAVObject portion of the root of the split" <<endl;
	//Get the NiAVObject portion of the root of the split
	avObj->SetName(tempAV->GetName());
	avObj->SetVisibility(tempAV->GetVisibility());
	avObj->SetFlags(tempAV->GetFlags());

	//If polygon mesh is hidden, hide tri_shape
	MPlug vis = visibleMeshFn.findPlug(MString("visibility"));
	bool visibility;
	vis.getValue(visibility);


	NiNodeRef splitRoot = DynamicCast<NiNode>(avObj);
	if (splitRoot != NULL) {
		//Root is a NiNode with NiTriBasedGeom children.
		vector<NiAVObjectRef> children = splitRoot->GetChildren();
		for (unsigned c = 0; c < children.size(); ++c) {
			//Set the default collision propogation flag to "use triangles"
			children[c]->SetFlags(2);
			// Make the mesh invisible if necessary
			if (visibility == false) {
				children[c]->SetVisibility(false);
			}
		}

	}
	else {
		//Root must be a NiTriBasedGeom.  Make it invisible if necessary
		if (visibility == false) {
			avObj->SetVisibility(false);
		}
	}

}
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;

   }

}
Example #16
0
	// Load texture data from a texture node
	MStatus Material::loadTexture(MFnDependencyNode* pTexNode,TexOpType& opType,MStringArray& uvsets,ParamList& params)
	{
		Texture tex;
		// Get texture filename
		MString filename, absFilename;
		MRenderUtil::exactFileTextureName(pTexNode->object(),absFilename);
		filename = absFilename.substring(absFilename.rindex('/')+1,absFilename.length()-1);
		MString command = "toNativePath(\"";
		command += absFilename;
		command += "\")";
		MGlobal::executeCommand(command,absFilename);
		tex.absFilename = absFilename;
		tex.filename = filename;
		tex.uvsetIndex = 0;
		tex.uvsetName = "";
		// Set texture operation type
		tex.opType = opType;
		// Get connections to uvCoord attribute of texture node
		MPlugArray texSrcPlugs;
		pTexNode->findPlug("uvCoord").connectedTo(texSrcPlugs,true,false);
		// Get place2dtexture node (if connected)
		MFnDependencyNode* pPlace2dTexNode = NULL;
		for (int j=0; j<texSrcPlugs.length(); j++)
		{
			if (texSrcPlugs[j].node().hasFn(MFn::kPlace2dTexture))
			{
				pPlace2dTexNode = new MFnDependencyNode(texSrcPlugs[j].node());
				continue;
			}
		}
		// Get uvChooser node (if connected)
		MFnDependencyNode* pUvChooserNode = NULL;
		if (pPlace2dTexNode)
		{
			MPlugArray placetexSrcPlugs;
			pPlace2dTexNode->findPlug("uvCoord").connectedTo(placetexSrcPlugs,true,false);
			for (int j=0; j<placetexSrcPlugs.length(); j++)
			{
				if (placetexSrcPlugs[j].node().hasFn(MFn::kUvChooser))
				{
					pUvChooserNode = new MFnDependencyNode(placetexSrcPlugs[j].node());
					continue;
				}
			}
		}
		// Get uvset index
		if (pUvChooserNode)
		{
			bool foundMesh = false;
			bool foundUvset = false;
			MPlug uvsetsPlug = pUvChooserNode->findPlug("uvSets");
			MPlugArray uvsetsSrcPlugs;
			for (int i=0; i<uvsetsPlug.evaluateNumElements() && !foundMesh; i++)
			{
				uvsetsPlug[i].connectedTo(uvsetsSrcPlugs,true,false);
				for (int j=0; j<uvsetsSrcPlugs.length() && !foundMesh; j++)
				{
					if (uvsetsSrcPlugs[j].node().hasFn(MFn::kMesh))
					{
						uvsetsSrcPlugs[j].getValue(tex.uvsetName);
						for (int k=0; k<uvsets.length() && !foundUvset; k++)
						{
							if (uvsets[k] == tex.uvsetName)
							{
								tex.uvsetIndex = k;
								foundUvset = true;
							}
						}
					}
				}
			}
		}
		// Get texture options from Place2dTexture node
		if (pPlace2dTexNode)
		{
			// Get address mode
			//U
			bool wrapU, mirrorU;
			pPlace2dTexNode->findPlug("wrapU").getValue(wrapU);
			pPlace2dTexNode->findPlug("mirrorU").getValue(mirrorU);
			if (mirrorU)
				tex.am_u = TAM_MIRROR;
			else if (wrapU)
				tex.am_u = TAM_WRAP;
			else
				tex.am_u = TAM_CLAMP;
			// V
			bool wrapV,mirrorV;
			pPlace2dTexNode->findPlug("wrapV").getValue(wrapV);
			pPlace2dTexNode->findPlug("mirrorV").getValue(mirrorV);
			if (mirrorV)
				tex.am_v = TAM_MIRROR;
			else if (wrapV)
				tex.am_v = TAM_WRAP;
			else
				tex.am_v = TAM_CLAMP;
			// Get texture scale
			double covU,covV;
			pPlace2dTexNode->findPlug("coverageU").getValue(covU);
			pPlace2dTexNode->findPlug("coverageV").getValue(covV);
			tex.scale_u = covU;
			if (fabs(tex.scale_u) < PRECISION)
				tex.scale_u = 0;
			tex.scale_v = covV;
			if (fabs(tex.scale_v) < PRECISION)
				tex.scale_v = 0;
			// Get texture scroll
			double transU,transV;
			pPlace2dTexNode->findPlug("translateFrameU").getValue(transU);
			pPlace2dTexNode->findPlug("translateFrameV").getValue(transV);
			tex.scroll_u = -0.5 * (covU-1.0)/covU - transU/covU;
			if (fabs(tex.scroll_u) < PRECISION)
				tex.scroll_u = 0;
			tex.scroll_v = 0.5 * (covV-1.0)/covV + transV/covV;
			if (fabs(tex.scroll_v) < PRECISION)
				tex.scroll_v = 0;
			// Get texture rotation
			double rot;
			pPlace2dTexNode->findPlug("rotateFrame").getValue(rot);
			tex.rot = -rot;
			if (fabs(rot) < PRECISION)
				tex.rot = 0;
		}
		// add texture to material texture list
		m_textures.push_back(tex);
		// free up memory
		if (pUvChooserNode)
			delete pUvChooserNode;
		if (pPlace2dTexNode)
			delete pPlace2dTexNode;

		return MS::kSuccess;
	}
Example #17
0
//
// Write the 'connectAttr' commands for all of a node's incoming
// connections.
//
void maTranslator::writeNodeConnections(fstream& f, const MObject& node)
{
	MFnDependencyNode	nodeFn(node);
	MPlugArray			plugs;

	nodeFn.getConnections(plugs);

	unsigned int		numBrokenConns = fBrokenConnSrcs.length();
	unsigned int		numPlugs = plugs.length();
	unsigned int		i;

	for (i = 0; i < numPlugs; i++)
	{
		//
		// We only care about connections where we are the destination.
		//
		MPlug		destPlug = plugs[i];
		MPlugArray	srcPlug;

		destPlug.connectedTo(srcPlug, true, false);

		if (srcPlug.length() > 0)
		{
			MObject				srcNode = srcPlug[0].node();
			MFnDependencyNode	srcNodeFn(srcNode);

			//
			// Don't write the connection if the source is not writable...
			//
			if (!srcNodeFn.canBeWritten()) continue;

			//
			// or the connection was made in a referenced file...
			//
			if (destPlug.isFromReferencedFile()) continue;

			//
			// or the plug is procedural...
			//
			if (destPlug.isProcedural()) continue;

			//
			// or it is a connection between a default node and a shared
			// node (because those will get set up automatically).
			//
			if (srcNodeFn.isDefaultNode() && nodeFn.isShared()) continue;

			f << "connectAttr \"";

			//
			// Default nodes get a colon at the start of their names.
			//
			if (srcNodeFn.isDefaultNode()) f << ":";

			f << srcPlug[0].partialName(true).asChar()
			  << "\" \"";

			if (nodeFn.isDefaultNode()) f << ":";

			f << destPlug.partialName(true).asChar()
			  << "\"";

			//
			// If the src plug is also one from which a broken
			// connection originated, then add the "-rd/referenceDest" flag
			// to the command.  That will help Maya to better adjust if the
			// referenced file has changed the next time it is loaded.
			//
			if (srcNodeFn.isFromReferencedFile())
			{
				unsigned int j;

				for (j = 0; j < numBrokenConns; j++)
				{
					if (fBrokenConnSrcs[j] == srcPlug[0])
					{
						f << " -rd \""
						  << fBrokenConnDests[j].partialName(true).asChar()
						  << "\"";

						break;
					}
				}
			}

			//
			// If the plug is locked, then add a "-l/lock" flag to the
			// command.
			//
			if (destPlug.isLocked()) f << " -l on";

			//
			// If the destination attribute is a multi for which index
			// does not matter, then we must add the "-na/nextAvailable"
			// flag to the command.
			//
			MObject			attr = destPlug.attribute();
			MFnAttribute	attrFn(attr);

			if (!attrFn.indexMatters()) f << " -na";

			f << ";" << endl;
		}
	}
}
Example #18
0
	// Load material data
	MStatus Material::load(MFnDependencyNode* pShader,MStringArray& uvsets,ParamList& params)
	{
		MStatus stat;
		clear();
		//read material name, adding the requested prefix
		MString tmpStr = params.matPrefix;
		if (tmpStr != "")
			tmpStr += "/";
		tmpStr += pShader->name();
		MStringArray tmpStrArray;
		tmpStr.split(':',tmpStrArray);
		m_name = "";
		for (int i=0; i<tmpStrArray.length(); i++)
		{
			m_name += tmpStrArray[i];
			if (i < tmpStrArray.length()-1)
				m_name += "_";
		}

		//check if we want to export with lighting off option
		m_lightingOff = params.lightingOff;

		// GET MATERIAL DATA

		// Check material type
		if (pShader->object().hasFn(MFn::kPhong))
		{
			stat = loadPhong(pShader);
		}
		else if (pShader->object().hasFn(MFn::kBlinn))
		{
			stat = loadBlinn(pShader);
		}
		else if (pShader->object().hasFn(MFn::kLambert))
		{
			stat = loadLambert(pShader);
		}
		else if (pShader->object().hasFn(MFn::kPluginHwShaderNode))
		{
			stat = loadCgFxShader(pShader);
		}
		else
		{
			stat = loadSurfaceShader(pShader);
		}

		// Get textures data
		MPlugArray colorSrcPlugs;
		MPlugArray texSrcPlugs;
		MPlugArray placetexSrcPlugs;
		if (m_isTextured)
		{
			// Translate multiple textures if material is multitextured
			if (m_isMultiTextured)
			{
				// Get layered texture node
				MFnDependencyNode* pLayeredTexNode = NULL;
				if (m_type == MT_SURFACE_SHADER)
					pShader->findPlug("outColor").connectedTo(colorSrcPlugs,true,false);
				else
					pShader->findPlug("color").connectedTo(colorSrcPlugs,true,false);
				for (int i=0; i<colorSrcPlugs.length(); i++)
				{
					if (colorSrcPlugs[i].node().hasFn(MFn::kLayeredTexture))
					{
						pLayeredTexNode = new MFnDependencyNode(colorSrcPlugs[i].node());
						continue;
					}
				}

				// Get inputs to layered texture
				MPlug inputsPlug = pLayeredTexNode->findPlug("inputs");

				// Scan inputs and export textures
				for (int i=inputsPlug.numElements()-1; i>=0; i--)
				{
					MFnDependencyNode* pTextureNode = NULL;
					// Search for a connected texture
					inputsPlug[i].child(0).connectedTo(colorSrcPlugs,true,false);
					for (int j=0; j<colorSrcPlugs.length(); j++)
					{
						if (colorSrcPlugs[j].node().hasFn(MFn::kFileTexture))
						{
							pTextureNode = new MFnDependencyNode(colorSrcPlugs[j].node());
							continue;
						}
					}

					// Translate the texture if it was found
					if (pTextureNode)
					{
						// Get blend mode
						TexOpType opType;
						short bm;
						inputsPlug[i].child(2).getValue(bm);
						switch(bm)
						{				
						case 0:
							opType = TOT_REPLACE;
							break;
						case 1:
							opType = TOT_ALPHABLEND;
							break;				
						case 4:
							opType = TOT_ADD;
							break;
						case 6:
							opType = TOT_MODULATE;
							break;
						default:
							opType = TOT_MODULATE;
						}

						stat = loadTexture(pTextureNode,opType,uvsets,params);
						delete pTextureNode;
						if (MS::kSuccess != stat)
						{
							std::cout << "Error loading layered texture\n";
							std::cout.flush();
							delete pLayeredTexNode;
							return MS::kFailure;
						}
					}
				}
				if (pLayeredTexNode)
					delete pLayeredTexNode;
			}
			// Else translate the single texture
			else
			{
				// Get texture node
				MFnDependencyNode* pTextureNode = NULL;
				if (m_type == MT_SURFACE_SHADER)
					pShader->findPlug("outColor").connectedTo(colorSrcPlugs,true,false);
				else
					pShader->findPlug("color").connectedTo(colorSrcPlugs,true,false);
				for (int i=0; i<colorSrcPlugs.length(); i++)
				{
					if (colorSrcPlugs[i].node().hasFn(MFn::kFileTexture))
					{
						pTextureNode = new MFnDependencyNode(colorSrcPlugs[i].node());
						continue;
					}
				}
				if (pTextureNode)
				{
					TexOpType opType = TOT_MODULATE;
					stat = loadTexture(pTextureNode,opType,uvsets,params);
					delete pTextureNode;
					if (MS::kSuccess != stat)
					{
						std::cout << "Error loading texture\n";
						std::cout.flush();
						return MS::kFailure;
					}
				}
			}
		}

		return MS::kSuccess;
	}
Example #19
0
void 
simpleFluidEmitter::volumeFluidEmitter(
	MFnFluid& 		fluid,
	const MMatrix&	fluidWorldMatrix,
	int 			plugIndex,
	MDataBlock& 	block,
	double 			dt,
	double			conversion,
	double			dropoff
)
//==============================================================================
//
//	Method:	
//
//		simpleFluidEmitter::volumeFluidEmitter
//
//	Description:
//
//		Emits fluid from points distributed over the surface of the 
//		emitter's owner object.
//
//	Parameters:
//
//		fluid:				fluid into which we are emitting
//		fluidWorldMatrix:	object->world matrix for the fluid
//		plugIndex:			identifies which fluid connected to the emitter
//							we are emitting into
//		block:				datablock for the emitter, to retrieve attribute
//							values
//		dt:					time delta for this frame
//		conversion:			mapping from UI emission rates to internal units
//		dropoff:			specifies how much emission rate drops off as
//							we move away from the local y-axis of the 
//							volume emitter shape.
//
//==============================================================================
{
	//	get emitter position and relevant matrices 
	//	
	MPoint emitterPos = getWorldPosition();
	MMatrix emitterWorldMatrix = getWorldMatrix();
	MMatrix fluidInverseWorldMatrix = fluidWorldMatrix.inverse();
	
	//	get emission rates for density, fuel, heat, and emission color
	//	
	double densityEmit = fluidDensityEmission( block );
	double fuelEmit = fluidFuelEmission( block );
	double heatEmit = fluidHeatEmission( block );
	bool doEmitColor = fluidEmitColor( block );
	MColor emitColor = fluidColor( block );
	
	//	rate modulation based on frame time, user value conversion factor, and
	//	standard emitter "rate" value (not actually exposed in most fluid
	//	emitters, but there anyway).
	//
	double theRate = getRate(block) * dt * conversion;
	
	//	find the voxels that intersect the bounding box of the volume
	//	primitive associated with the emitter
	//
	MBoundingBox bbox;
	if( !volumePrimitiveBoundingBox( bbox ) )
	{
		//	shouldn't happen
		//
		return;
	}
	
	//	transform volume primitive into fluid space
	//
	bbox.transformUsing( emitterWorldMatrix );
	bbox.transformUsing( fluidInverseWorldMatrix );
	MPoint lowCorner = bbox.min();
	MPoint highCorner = bbox.max();

	// see if autoresize to emitter is on, so we can resize before emitting
	// 
	// unfortunately, we need the fluidShape itself in order to check
	// we'll just look at the first connected fluid,
	// walking the multi is left as an excercise for the reader
	// similarly, determining whether there is start frame emission
	// and resizing at the start frame, or not, is left as an excercise
	// and finally, emission with autoResize will need to include the dynamicOffset
	// 
	MObject			thisObj = thisMObject();
	MFnDependencyNode	nodeFn(thisObj);
	
	bool autoResize = false;
	bool resizeToEmitter = false;
	MPlug fnPlug = nodeFn.findPlug("emissionFunction");
	if(fnPlug.isConnected()) {
		MPlugArray connections;
		fnPlug.connectedTo(connections, false, true);
		if (connections.length() > 0) {
			MObject sourceNode = connections[0].node();
			if (sourceNode.hasFn(MFn::kFluid)) {
		   		MFnFluid fluidFn(sourceNode);
				autoResize = fluidFn.isAutoResize();
				resizeToEmitter =  fluidFn.isResizeToEmitter();
				if(autoResize && resizeToEmitter) {
					fluidFn.expandToInclude(lowCorner, highCorner);
				}
			}
		}
	}
	if(autoResize && resizeToEmitter) {
		fluid.updateGrid ();
	}

	//	get voxel dimensions and sizes (object space)
	//
	double size[3];
	unsigned int res[3];
	fluid.getDimensions( size[0], size[1], size[2] );
	fluid.getResolution( res[0], res[1], res[2] );

	//	voxel sizes
	double dx = size[0] / res[0];
	double dy = size[1] / res[1];
	double dz = size[2] / res[2];
	
	// 	voxel centers
	double Ox = -size[0]/2;
	double Oy = -size[1]/2;
	double Oz = -size[2]/2;	

	//	get fluid voxel coord range of bounding box
	//
	int3 lowCoords;
	int3 highCoords;
	fluid.toGridIndex( lowCorner, lowCoords );
	fluid.toGridIndex( highCorner, highCoords );
	
	int i;
	for ( i = 0; i < 3; i++ )
	{
		if ( lowCoords[i] < 0 ) {
			lowCoords[i] = 0;
		} else if ( lowCoords[i] > ((int)res[i])-1 ) {
			lowCoords[i] = ((int)res[i])-1;
		}

		if ( highCoords[i] < 0 ) {
			highCoords[i] = 0;
		} else if ( highCoords[i] > ((int)res[i])-1 ) {
			highCoords[i] = ((int)res[i])-1;
		}
		
	}

	//	figure out the emitter size relative to the voxel size, and compute
	//	a per-voxel sampling rate that uses 1 sample/voxel for emitters that
	//	are >= 2 voxels big in all dimensions.  For smaller emitters, use up
	//	to 8 samples per voxel.
	//
	double emitterVoxelSize[3];
	emitterVoxelSize[0] = (highCorner[0]-lowCorner[0])/dx;
	emitterVoxelSize[1] = (highCorner[1]-lowCorner[1])/dy;
	emitterVoxelSize[2] = (highCorner[2]-lowCorner[2])/dz;
		
	double minVoxelSize = MIN(emitterVoxelSize[0],MIN(emitterVoxelSize[1],emitterVoxelSize[2]));
	if( minVoxelSize < 1.0 )
	{
		minVoxelSize = 1.0;
	}
	int maxSamples = 8;
	int numSamples = (int)(8.0/(minVoxelSize*minVoxelSize*minVoxelSize) + 0.5);
	if( numSamples < 1 ) numSamples = 1;
	if( numSamples > maxSamples ) numSamples = maxSamples;
	
	//	non-jittered, just use one sample in the voxel center.  Should replace
	//	with uniform sampling pattern.
	//
	bool jitter = fluidJitter(block);
	if( !jitter )
	{
		numSamples = 1;
	}
	
	//	for each voxel that could potentially intersect the volume emitter
	//	primitive, take some samples in the voxel.  For those inside the
	//	volume, compute their dropoff relative to the primitive's local y-axis,
	//	and emit an appropriate amount into the voxel.
	//
	for( i = lowCoords[0]; i <= highCoords[0]; i++ )
	{
		double x = Ox + (i+0.5)*dx;
			
		for( int j = lowCoords[1]; j < highCoords[1]; j++ )
		{
			double y = Oy + (j+0.5)*dy;

			for( int k = lowCoords[2]; k < highCoords[2]; k++ )
			{
				double z = Oz + (k+0.5)*dz;
				
				for ( int si = 0; si < numSamples; si++) {
					
					//	compute voxel sample point (object space)
					//
					double rx, ry, rz;
					if(jitter) {
						rx = x + dx*(randgen() - 0.5);
						ry = y + dy*(randgen() - 0.5);
						rz = z + dz*(randgen() - 0.5);
					} else {
						rx = x;
						ry = y;
						rz = z;
					}
					
					//	to world space
					MPoint pt( rx, ry, rz );
					pt *= fluidWorldMatrix;

					//	test to see if point is inside volume primitive
					//
					if( volumePrimitivePointInside( pt, emitterWorldMatrix ) )
					{
						//	compute dropoff
						//
						double dist = pt.distanceTo( emitterPos );
						double distDrop = dropoff * (dist*dist);
						double newVal = (theRate * exp( -distDrop )) / (double)numSamples;
						
						//	emit into arrays
						//
						if( newVal != 0.0 )
						{
							fluid.emitIntoArrays( (float) newVal, i, j, k, (float)densityEmit, (float)heatEmit, (float)fuelEmit, doEmitColor, emitColor );
						}
					}
				}
			}
		}
	}
}
bool FxAttributeFiller::FillScript( DXCCEffectPath& parameter, MPlug& plug )

{
	MString plugName= Shader->EncodePlug(plug);

	MString MELPlugName= MFnDependencyNode(plug.node()).name() + MString(".") + plugName;

	switch(parameter.End->Description.Class)
	{
	case D3DXPC_SCALAR:
		{
			if( 0 == lstrcmpiA( SasUiControl.asChar(), "Slider"))
			{
				Script.AppendFormat("\tdxfxControlSliderCreate(\"float\", \"%s\", \"%f\", \"%f\", \"%d\", \"%s\");\n", SasUiLabel.asChar(), SasUiMin, SasUiMax, SasUiSteps, MELPlugName.asChar() );
			}
			else
			{
				Script.AppendFormat("\tdxfxControlScalarCreate(\"float\", \"%s\", \"%s\");\n", SasUiLabel.asChar(), MELPlugName.asChar());
			}
		}
		break;
	case D3DXPC_VECTOR:
		{
			if( 0 == lstrcmpiA( SasUiControl.asChar(), "ColorPicker") 
				&& parameter.End->Description.Columns >= 3)
			{//COLOR
				Script.AppendFormat("\tdxfxControlColorCreate(\"%s\", \"%s\", %d);\n", SasUiLabel.asChar(), MELPlugName.asChar(), parameter.End->Description.Columns);
			}
			else
			{//VECTOR
				Script.AppendFormat("\tdxfxControlVectorCreate(\"float\", \"%s\", \"%s\", %d);\n", SasUiLabel.asChar(), MELPlugName.asChar(), parameter.End->Description.Columns);
			}
		}
		break;				
	case D3DXPC_MATRIX_ROWS:
	case D3DXPC_MATRIX_COLUMNS:
		{
			Script.AppendFormat("\tdxfxControlMatrixCreate(\"float\", \"%s\", \"%s\", %d, %d);\n", SasUiLabel.asChar(), MELPlugName.asChar(), parameter.End->Description.Rows, parameter.End->Description.Columns);
		}
		break;	
	case D3DXPC_OBJECT:
		switch(parameter.End->Description.Type)
		{
		case D3DXPT_STRING:
			{
				Script.AppendFormat("\tdxfxControlStringCreate(\"%s\", \"%s\");\n", SasUiLabel.asChar(), MELPlugName.asChar());
			}
			break;
		case D3DXPT_TEXTURE:
		case D3DXPT_TEXTURE1D:
		case D3DXPT_TEXTURE2D:
		case D3DXPT_TEXTURE3D:
		case D3DXPT_TEXTURECUBE:
			{
				Script.AppendFormat("\tdxfxControlTextureCreate(\"%s\", \"%s\");\n", SasUiLabel.asChar(), MELPlugName.asChar());
			}
			break;
		default:
			break;
		};
		break;
	default:
		break;
	};

	return true;
}
Example #21
0
// Load an animation clip
MStatus skeleton::loadClip(MString clipName,int start,int stop,int rate)
{
	uint fps = getFps();
	float frameTime = 1000.0f / fps;

	MStatus stat;
	int i,j;
	std::vector<int> times;
	if (m_joints.size() < 0)
		return MS::kFailure;

	times.clear();
	for (int t=start; t<stop; t+=rate)
		times.push_back(t);
	times.push_back(stop);

	// create the animation
	animation a;
	a.name = clipName.asChar();
	
	if(m_animations.size() == 0)
	{
		a.startTime = 0;
		a.endTime = times[times.size()-1] - times[0];
	}
	else
	{
		a.startTime = m_animations[m_animations.size()-1].endTime + 1;
		a.endTime = a.startTime + times[times.size()-1] - times[0];
	}

	m_animations.push_back(a);
	int animIdx = m_animations.size() - 1;

	for (i=0; i<times.size(); i++)
	{
		MAnimControl::setCurrentTime(MTime(times[i],MTime::uiUnit()));
		for (j=0; j<m_joints.size(); j++)
		{
			keyframeTranslation translation;
			keyframeRotation rotation;
			keyframeScale scale;

			joint &jt = m_joints[j];
			int time = times[i] - times[0] + a.startTime;
			loadKeyframe(m_joints[j],time,translation,rotation,scale);
			translation.time *= frameTime;
			rotation.time *= frameTime;
			scale.time *= frameTime;

			size_t size = jt.keyframesTranslation.size();
			if(size > 0)
			{
				keyframeTranslation& t = jt.keyframesTranslation[size - 1];
				if(!equal(translation.v[0],t.v[0]) || !equal(translation.v[1],t.v[1]) || !equal(translation.v[2],t.v[2]))
				{
					//如果跟上一次不一样,并且跨越了桢,那么需要补一桢
					int lastTime = Round(t.time / frameTime);
					if(time - 1 > lastTime)
					{
						keyframeTranslation temp = t;
						temp.time = (time - 1) * frameTime;
						jt.keyframesTranslation.push_back(temp);
					}
					jt.keyframesTranslation.push_back(translation);
				}
			}
			else
			{
				jt.keyframesTranslation.push_back(translation);
			}

			MFnIkJoint jn(jt.jointDag);
			if(jn.name() == "Hips")
			{
//				breakable;
			}
			size = jt.keyframesRotation.size();
			if(size > 0)
			{
				keyframeRotation& r = jt.keyframesRotation[size - 1];
				if(!equal(rotation.q[0],r.q[0]) || !equal(rotation.q[1],r.q[1]) || !equal(rotation.q[2],r.q[2]) || !equal(rotation.q[3],r.q[3]))
				{
					//如果跟上一次不一样,并且跨越了桢,那么需要补一桢
					int lastTime = Round(r.time / frameTime);
					if(time - 1 > lastTime)
					{
						keyframeRotation temp = r;
						temp.time = (time - 1) * frameTime;
						jt.keyframesRotation.push_back(temp);
					}
					jt.keyframesRotation.push_back(rotation);
				}
			}
			else
			{
				jt.keyframesRotation.push_back(rotation);
			}
			size = jt.keyframesScale.size();
			if(size > 0)
			{
				keyframeScale& s = jt.keyframesScale[size - 1];
				if(!equal(scale.v[0],s.v[0]) || !equal(scale.v[1],s.v[1]) || !equal(scale.v[2],s.v[2]))
				{
					//如果跟上一次不一样,并且跨越了桢,那么需要补一桢
					int lastTime = Round(s.time / frameTime);
					if(time - 1 > lastTime)
					{
						keyframeScale temp = s;
						temp.time = (time - 1) * frameTime;
						jt.keyframesScale.push_back(temp);
					}
					jt.keyframesScale.push_back(scale);
				}
			}
			else
			{
				jt.keyframesScale.push_back(scale);
			}

			if(jt.hasRibbonSystem)
			{
				keyframeT<bool> keyframeVisible;
				keyframeT<float> keyframeAbove;
				keyframeT<float> keyframeBelow;
				keyframeT<short> keyframeSlot;
				keyframeT<float3> keyframeColor;
				keyframeT<float> keyframeAlpha;

				MFnIkJoint jointFn(jt.jointDag);
				MPlug plug;

				plug = jointFn.findPlug("unRibbonVisible");
				bool visible;
				plug.getValue(visible);
				plug = jointFn.findPlug("unRibbonAbove");
				float above;
				plug.getValue(above);
				plug = jointFn.findPlug("unRibbonBelow");
				float below;
				plug.getValue(below);
				plug = jointFn.findPlug("unRibbonTextureSlot");
				short slot;
				plug.getValue(slot);
				plug = jointFn.findPlug("unRibbonVertexColor");
				MObject object;
				plug.getValue(object);
				MFnNumericData data(object);
				float r,g,b;
				data.getData(r,g,b);
				plug = jointFn.findPlug("unRibbonVertexAlpha");
				float alpha;
				plug.getValue(alpha);

				keyframeVisible.time = time * frameTime;
				keyframeAbove.time = time * frameTime;
				keyframeBelow.time = time * frameTime;
				keyframeSlot.time = time * frameTime;
				keyframeColor.time = time * frameTime;
				keyframeAlpha.time = time * frameTime;

				keyframeVisible.data = visible;
				keyframeAbove.data = above;
				keyframeBelow.data = below;
				keyframeSlot.data = slot;
				keyframeColor.data[0] = r;
				keyframeColor.data[1] = g;
				keyframeColor.data[2] = b;
				keyframeAlpha.data = alpha;

				addKeyFramesBool(&jt.ribbon.keyframesVisible,&keyframeVisible);
				addKeyFramesFloat(&jt.ribbon.keyframeAbove,&keyframeAbove);
				addKeyFramesFloat(&jt.ribbon.keyframeBelow,&keyframeBelow);
				size = jt.ribbon.keyframeSlot.size();
				if(size > 0)
				{
					keyframeT<short>& s = jt.ribbon.keyframeSlot[size - 1];
					if(s.data == slot)
					{
						jt.ribbon.keyframeSlot.push_back(keyframeSlot);
					}
				}
				else
				{
					jt.ribbon.keyframeSlot.push_back(keyframeSlot);
				}
				size = jt.ribbon.keyframeColor.size();
				if(size > 0)
				{
					keyframeT<float3>& s = jt.ribbon.keyframeColor[size - 1];
					if(!equal(s.data[0],r) || !equal(s.data[1],g) || !equal(s.data[2],b))
					{
						jt.ribbon.keyframeColor.push_back(keyframeColor);
					}
				}
				else
				{
					jt.ribbon.keyframeColor.push_back(keyframeColor);
				}
				addKeyFramesFloat(&jt.ribbon.keyframeAlpha,&keyframeAlpha);
			}
			if(jt.hasParticleSystem)
			{
				keyframeT<bool> keyframeVisible;
				keyframeT<float> keyframeSpeed;
				keyframeT<float> keyframeVariation;
				keyframeT<float> keyframeConeAngle;
				keyframeT<float> keyframeGravity;
				keyframeT<float> keyframeExplosiveForce;
				keyframeT<float> keyframeEmissionRate;
				keyframeT<float> keyframeWidth;
				keyframeT<float> keyframeLength;
				keyframeT<float> keyframeHeight;

				MFnIkJoint jointFn(jt.jointDag);
				MPlug plug;

				plug = jointFn.findPlug("unParticleVisible");
				bool visible;
				plug.getValue(visible);
				plug = jointFn.findPlug("unParticleSpeed");
				float speed;
				plug.getValue(speed);
				plug = jointFn.findPlug("unParticleVariationPercent");
				float variation;
				plug.getValue(variation);
				plug = jointFn.findPlug("unParticleConeAngle");
				float coneAngle;
				plug.getValue(coneAngle);
				plug = jointFn.findPlug("unParticleGravity");
				float gravity;
				plug.getValue(gravity);
				plug = jointFn.findPlug("unParticleExplosiveForce");
				float explosiveForce = 0.0f;
				if(!plug.isNull())
				{
					plug.getValue(explosiveForce);
				}
				plug = jointFn.findPlug("unParticleEmissionRate");
				float emissionRate;
				plug.getValue(emissionRate);
				plug = jointFn.findPlug("unParticleEmitterWidth");
				float width;
				plug.getValue(width);
				plug = jointFn.findPlug("unParticleEmitterLength");
				float length;
				plug.getValue(length);
				plug = jointFn.findPlug("unParticleEmitterHeight");
				float height = 0.0f;
				if(!plug.isNull())
				{
					plug.getValue(height);
				}

				keyframeVisible.time = time * frameTime;
				keyframeSpeed.time = time * frameTime;
				keyframeVariation.time = time * frameTime;
				keyframeConeAngle.time = time * frameTime;
				keyframeGravity.time = time * frameTime;
				keyframeExplosiveForce.time = time * frameTime;
				keyframeEmissionRate.time = time * frameTime;
				keyframeWidth.time = time * frameTime;
				keyframeLength.time = time * frameTime;
				keyframeHeight.time = time * frameTime;

				keyframeVisible.data = visible;
				keyframeSpeed.data = speed;
				keyframeVariation.data = variation / 100.0f;
				keyframeConeAngle.data = coneAngle;
				keyframeGravity.data = gravity;
				keyframeExplosiveForce.data = explosiveForce;
				keyframeEmissionRate.data = emissionRate;
				keyframeWidth.data = width;
				keyframeLength.data = length;
				keyframeHeight.data = height;

				addKeyFramesBool(&jt.particle.keyframesVisible,&keyframeVisible);
				addKeyFramesFloat(&jt.particle.keyframesSpeed,&keyframeSpeed);
				addKeyFramesFloat(&jt.particle.keyframesVariation,&keyframeVariation);
				addKeyFramesFloat(&jt.particle.keyframesConeAngle,&keyframeConeAngle);
				addKeyFramesFloat(&jt.particle.keyframesGravity,&keyframeGravity);
				addKeyFramesFloat(&jt.particle.keyframesExplosiveForce,&keyframeExplosiveForce);
				addKeyFramesFloat(&jt.particle.keyframesEmissionRate,&keyframeEmissionRate);
				addKeyFramesFloat(&jt.particle.keyframesWidth,&keyframeWidth);
				addKeyFramesFloat(&jt.particle.keyframesLength,&keyframeLength);
				addKeyFramesFloat(&jt.particle.keyframesHeight,&keyframeHeight);
			}
		}
	}

	return MS::kSuccess;
}
bool FxAttributeFiller::FillPlug( DXCCEffectPath& parameter, MPlug& plug )
{
	HRESULT hr= S_OK;
	LPDXCCRESOURCE pResource= NULL;
	LPDIRECT3DBASETEXTURE9 pTexture= NULL;
	D3DXPARAMETER_DESC desc= parameter.End->Description;
	float NumericVals[16]= {0.0f};
	MString StringVal;
	LPCSTR StringValStr= "";

	bool RestoreFound= false;
	LPCVOID pRestoreData= NULL;
	size_t RestoreSize= 0;
	CComPtr<IDXCCPropertyCollection> pCollection;
	DXCCPROPERTY_KEY key= 0;

	if(Restore)
	{
		if( DXCC_SUCCEEDED( Restore->GetPath( parameter.End->LongPathName, &pCollection, &key) ) )
		{
			pCollection->GetPropertyValueAsData(key, &pRestoreData);
			DXCCPROPERTY_DESC desc= pCollection->GetPropertyDesc(key);

			if(desc == DXCCPD_STRING)
			{
				StringVal= (LPCSTR)pRestoreData;
				StringValStr= (LPCSTR)pRestoreData;

				RestoreFound= true;
			}
			else
			{
				size_t RestoreSize= DXCCPropertySize( desc, pRestoreData );
				memcpy( NumericVals, pRestoreData, RestoreSize);

				RestoreFound= true;
			}
		}
	}



	if((desc.Type == D3DXPT_BOOL)
	||(desc.Type == D3DXPT_INT)
	||(desc.Type == D3DXPT_FLOAT))
	{

		if(!RestoreFound)
		{

			if(plug.isArray())
			{
				hr=  Shader->Effect->GetFloatArray(parameter.End->Handle, NumericVals, 16);
					if(DXCC_FAILED(hr))
						DXCC_GOTO_EXIT(e_Exit, TRUE);
			}
			else
			{
				hr=  Shader->Effect->GetFloat(parameter.End->Handle, NumericVals);
				if(DXCC_FAILED(hr))
					DXCC_GOTO_EXIT(e_Exit, TRUE);
			}
		}

		if(plug.isArray())
		{
			int count= desc.Rows * desc.Columns;
			for(int i= 0; i < count; i++)
			{
				MPlug subPlug= plug.elementByLogicalIndex(i);
				DXCHECK_MSTATUS(subPlug.setValue( NumericVals[i] ));
			}
		}
		else
		{
			DXCHECK_MSTATUS(plug.setValue( NumericVals[0] ));
		}
	}
	else if((desc.Type == D3DXPT_TEXTURE)
	||(desc.Type == D3DXPT_TEXTURE1D)
	||(desc.Type == D3DXPT_TEXTURE2D)
	||(desc.Type == D3DXPT_TEXTURE3D)
	||(desc.Type == D3DXPT_TEXTURECUBE))
	{

		if(!RestoreFound)
		{
			hr=  Shader->Effect->GetTexture(parameter.End->Handle, &pTexture);
			if(DXCC_SUCCEEDED(hr) && pTexture != NULL)
			{
				hr= g_PreviewPipeline.AccessManager()->FindResourceByPointer(
						(LPUNKNOWN)pTexture, 
						NULL, 
						&pResource);
				if(DXCC_SUCCEEDED(hr))
				{
					StringVal= pResource->GetResourcePath();
				}
			}
			else
			{
				D3DXHANDLE hResourceAddy= Shader->Effect->GetAnnotationByName( parameter.End->Handle, "SasResourceAddress");
				if(hResourceAddy)
				{
					LPCSTR resourceAddressStr= NULL;
					Shader->Effect->GetString(hResourceAddy, &resourceAddressStr); 

					StringVal= resourceAddressStr;
				}
			}
		}

		DXCHECK_MSTATUS(plug.setValue( StringVal ));
	}
	else if(desc.Type == D3DXPT_STRING)
	{
		if(!RestoreFound)
		{
			hr=  Shader->Effect->GetString(parameter.End->Handle, &StringValStr);
			StringVal= StringValStr;
		}

		DXCHECK_MSTATUS(plug.setValue( StringVal ));
	}
	else
	{
		DXCC_STATUS_EXIT(hr, E_FAIL, e_Exit, TRUE);
	}

e_Exit:
	DXCC_RELEASE(pResource);
	DXCC_RELEASE(pTexture);

	return DXCC_SUCCEEDED(hr);
}
Example #23
0
ConstObjectPtr LiveScene::readAttribute( const Name &name, double time ) const
{
	if ( !m_isRoot && m_dagPath.length() == 0 )
	{
		throw Exception( "IECoreMaya::LiveScene::readAttribute: Dag path no longer exists!" );
	}
	
	tbb::mutex::scoped_lock l( s_mutex );
	if ( !m_isRoot )
	{

		if( name == SceneInterface::visibilityName )
		{
			bool visible = true;

			MStatus st;
			MFnDagNode dagFn( m_dagPath );
			MPlug visibilityPlug = dagFn.findPlug( MPxTransform::visibility, &st );
			if( st )
			{
				visible = visibilityPlug.asBool();
			}

			if( visible )
			{
				MDagPath childDag;

				// find an object that's either a SceneShape, or has a cortex converter and check its visibility:
				unsigned int childCount = 0;
				m_dagPath.numberOfShapesDirectlyBelow(childCount);

				for ( unsigned int c = 0; c < childCount; c++ )
				{
					MDagPath d = m_dagPath;
					if( d.extendToShapeDirectlyBelow( c ) )
					{
						MFnDagNode fnChildDag(d);
						if( fnChildDag.typeId() == SceneShape::id )
						{
							childDag = d;
							break;
						}

						if ( fnChildDag.isIntermediateObject() )
						{
							continue;
						}

						FromMayaShapeConverterPtr shapeConverter = FromMayaShapeConverter::create( d );
						if( shapeConverter )
						{
							childDag = d;
							break;
						}

						FromMayaDagNodeConverterPtr dagConverter = FromMayaDagNodeConverter::create( d );
						if( dagConverter )
						{
							childDag = d;
							break;
						}
					}
				}

				if( childDag.isValid() )
				{
					MFnDagNode dagFn( childDag );
					MPlug visibilityPlug = dagFn.findPlug( MPxSurfaceShape::visibility, &st );
					if( st )
					{
						visible = visibilityPlug.asBool();
					}
				}

			}

			return new BoolData( visible );
		}

	}
	else if( name == SceneInterface::visibilityName )
	{
		return new BoolData( true );
	}

	std::vector< CustomAttributeReader > &attributeReaders = customAttributeReaders();
	for ( std::vector< CustomAttributeReader >::const_reverse_iterator it = attributeReaders.rbegin(); it != attributeReaders.rend(); ++it )
	{
		ConstObjectPtr attr = it->m_read( m_dagPath, name );
		if( !attr )
		{
			continue;
		}
		return attr;
	}

	if( strstr( name.c_str(), "user:"******"ieAttr_" + name.string().substr(5) ).c_str(), false, &st );
		if( st )
		{
			FromMayaConverterPtr plugConverter = FromMayaPlugConverter::create( attrPlug );
			if( !plugConverter )
			{
				return IECore::NullObject::defaultNullObject();
			}
			return plugConverter->convert();
		}
	}

	return IECore::NullObject::defaultNullObject();
}
MStatus slopeShaderBehavior::connectNodeToNode( MObject &sourceNode, MObject &destinationNode, bool force )
//
//	Description:
//		Overloaded function from MPxDragAndDropBehavior
//	this method will handle the connection between the slopeShader and the shader it is
//	assigned to as well as any meshes that it is assigned to. 
//
{
	MStatus result = MS::kFailure;
	MFnDependencyNode src(sourceNode);

	//if we are dragging from a lambert
	//we want to check what we are dragging
	//onto.
	if(sourceNode.hasFn(MFn::kLambert))
	{
		MObject shaderNode;
		MPlugArray connections;
		MObjectArray shaderNodes;
		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);
		unsigned i;
		for(i = 0; i < connections.length(); i++)
		{
			//check the incoming connections to this plug
			//
			MPlugArray connectedPlugs;
			connections[i].connectedTo(connectedPlugs, true, false);
			for(unsigned 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[j].node();
				if(MFnDependencyNode(currentnode).typeName() == "slopeShader")
				{
					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(destinationNode);
			if(destinationNode.hasFn(MFn::kMesh))
			{
				//if the node is a mesh than for each slopeShader
				//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 = MFnDependencyNode(shaderNodes[i]).findPlug("dirtyShaderPlug");

					if(!srcPlug.isNull() && !destPlug.isNull())
					{
						MString cmd = "connectAttr -na ";
						cmd += srcPlug.name() + " ";
						cmd += destPlug.name();
						MGlobal::executeCommand(cmd);
					}
				}

				//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())
				{
					MString cmd = "sets -edit -forceElement ";
					cmd += MFnDependencyNode(shadingEngine).name() + " ";
					cmd += MFnDagNode(destinationNode).partialPathName();
					result = MGlobal::executeCommand(cmd);
				}
			}
		}
	}
	else if(src.typeName() == "slopeShader")
	//if we are dragging from a slope shader
	//than we want to see what we are dragging onto
	//
	{
		if(destinationNode.hasFn(MFn::kMesh))
		{
			//if the user is dragging onto a mesh
			//than make the connection from the worldMesh
			//to the dirtyShader plug on the slopeShader
			//
			MFnDependencyNode dest(destinationNode);
			MPlug srcPlug = dest.findPlug("worldMesh");
			MPlug destPlug = src.findPlug("dirtyShaderPlug");
			if(!srcPlug.isNull() && !destPlug.isNull())
			{
				MString cmd = "connectAttr -na ";
				cmd += srcPlug.name() + " ";
				cmd += destPlug.name();
				result = MGlobal::executeCommand(cmd);
			}
		}
	}

	return result;
}
Example #25
0
MStatus liqSurfaceNode::compute( const MPlug& plug, MDataBlock& block )
{
  // outColor or individual R, G, B channel
  if( (plug == aOutColor) || (plug.parent() == aOutColor) ||
	  (plug == aOutTransparency) || (plug.parent() == aOutTransparency)
  	) {

    //cout <<"compute... "<<endl;

    // init shader
    MStatus status;
    MFloatVector theColor( 0.0f, 0.0f, 0.0f );
    MFloatVector& cColor  = block.inputValue(aColor).asFloatVector();
    MFloatVector& cTrans  = block.inputValue(aOpacity).asFloatVector();
    MFloatVector& ctex    = block.inputValue(aGLPreviewTexture).asFloatVector();

    // exploit maya's free openGL preview
    if ( ctex != MFloatVector( -1.0, -1.0, -1.0 ) ) theColor = ctex;
    else theColor = cColor;

    MFloatVector resultColor( 0.0, 0.0, 0.0 );
    MFloatVector resultTrans( cTrans );



    // lambert calc -------------------
    bool&  ignoreLights = block.inputValue( aMayaIgnoreLights, &status ).asBool();
    float& Ka = block.inputValue( aMayaKa, &status ).asFloat();
    float& Kd = block.inputValue( aMayaKd, &status ).asFloat();

    // get surface normal
    MFloatVector& surfaceNormal = block.inputValue( aNormalCamera, &status ).asFloatVector();
    CHECK_MSTATUS( status );

    if ( ignoreLights ) {

      MFloatVector cam( 0.0, 0.0, 1.0 );
      float cosln = cam * surfaceNormal;
      if ( cosln > 0.0f ) {
        float diff = cosln * cosln * Kd + Ka;
        resultColor = diff * theColor;
      }

    } else {

      // Get light list
      MArrayDataHandle lightData = block.inputArrayValue( aLightData, &status );
      CHECK_MSTATUS( status );
      int numLights = lightData.elementCount( &status );
      CHECK_MSTATUS( status );

      // Iterate through light list and get ambient/diffuse values
      for( int count=1; count <= numLights; count++ )
      {
        // Get the current light out of the array
        MDataHandle currentLight = lightData.inputValue( &status );
        CHECK_MSTATUS( status );

        // Get the intensity of that light
        MFloatVector& lightIntensity = currentLight.child( aLightIntensity ).asFloatVector();

        // Find ambient component
        if ( currentLight.child( aLightAmbient ).asBool() ) {
          resultColor += lightIntensity;
        }

        // Find diffuse component
        if ( currentLight.child( aLightDiffuse ).asBool() ) {
          MFloatVector& lightDirection = currentLight.child( aLightDirection ).asFloatVector();
          float cosln = lightDirection * surfaceNormal;
          if ( cosln > 0.0f )  resultColor += lightIntensity * cosln * Kd ;
        }

        // Advance to the next light.
        if ( count < numLights ) {
          status = lightData.next();
          CHECK_MSTATUS( status );
        }
      }

      resultColor[0] *= theColor[0];
      resultColor[1] *= theColor[1];
      resultColor[2] *= theColor[2];

    }

    resultTrans[0] = ( 1 - resultTrans[0] );
    resultTrans[1] = ( 1 - resultTrans[1] );
    resultTrans[2] = ( 1 - resultTrans[2] );


    // set ouput color attribute
    MDataHandle outColorHandle = block.outputValue( aOutColor );
    MFloatVector& outColor = outColorHandle.asFloatVector();
    outColor = resultColor;
    outColorHandle.setClean();

    MDataHandle outTransHandle = block.outputValue( aOutTransparency );
    MFloatVector& outTrans = outTransHandle.asFloatVector();
    outTrans = resultTrans;
    outTransHandle.setClean();

  } else return MS::kUnknownParameter;


  return MS::kSuccess;
}
Example #26
0
MStatus nodeInfo::doIt( const MArgList& args )
//
// Description
//     This method performs the action of the command.
//
//     This method iterates over all selected items and
//     prints out connected plug and dependency node type
//     information.
//
{
	MStatus stat;			// Status code
	MObject dependNode;		// Selected dependency node

	stat = parseArgs ( args );
	if ( !stat )
		return stat;

	// Create a selection list iterator
	//
	MSelectionList slist;
	MGlobal::getActiveSelectionList( slist );
	MItSelectionList iter( slist, MFn::kInvalid,&stat );


	// Iterate over all selected dependency nodes
	//
	for ( ; !iter.isDone(); iter.next() ) 
	{
		// Get the selected dependency node
		//
		stat = iter.getDependNode( dependNode );
		if ( !stat ) {
			stat.perror("getDependNode");
			continue;
		}

		// Create a function set for the dependency node
		//
		MFnDependencyNode fnDependNode( dependNode );

		// Check the type of the dependency node
		//
		MString nodeName = fnDependNode.name();
		nodeName += ": ";
		printType( dependNode, nodeName );

		// Get all connected plugs to this node
		//
		MPlugArray connectedPlugs;
		stat = fnDependNode.getConnections( connectedPlugs );

		int numberOfPlugs = connectedPlugs.length();
		if ( !quiet )
			cerr << "  Found: " << numberOfPlugs << " connections" << endl;

		// Print out the dependency node name and attributes
		// for each plug
		//
		for ( int i=0; i<numberOfPlugs; i++ ) 
		{
			MPlug plug = connectedPlugs[i];
			MString pinfo = plug.info();
			if ( !quiet )
				cerr << "  Plug info: " << pinfo << endl;

			// Now get the plugs that this plug is the
			// destination of and print the node type.
			//
			MPlugArray array;
			plug.connectedTo( array, true, false );

			for ( unsigned int j=0; j<array.length(); j++ )
			{
				MObject mnode = array[j].node();
				MString msg( "    This plug is a dest of a " );
				printType( mnode, msg );
			}
		}
	}
	return MS::kSuccess;
}
Example #27
0
MStatus AbcExport::doIt(const MArgList & args)
{
try
{
    MStatus status;
    
    util::clearIsAnimatedCache();

    MTime oldCurTime = MAnimControl::currentTime();

    MArgParser argData(syntax(), args, &status);

    if (argData.isFlagSet("help"))
    {
        MGlobal::displayInfo(util::getHelpText());
        return MS::kSuccess;
    }

    bool verbose = argData.isFlagSet("verbose");

    // If skipFrame is true, when going through the playback range of the
    // scene, as much frames are skipped when possible.  This could cause
    // a problem for, time dependent solutions like
    // particle system / hair simulation
    bool skipFrame = true;
    if (argData.isFlagSet("dontSkipUnwrittenFrames"))
        skipFrame = false;

    double startEvaluationTime = DBL_MAX;
    if (argData.isFlagSet("preRollStartFrame"))
    {
        double startAt = 0.0;
        argData.getFlagArgument("preRollStartFrame", 0, startAt);
        startEvaluationTime = startAt;
    }

    unsigned int jobSize = argData.numberOfFlagUses("jobArg");

    if (jobSize == 0)
        return status;

    // the frame range we will be iterating over for all jobs,
    // includes frames which are not skipped and the startAt offset
    std::set<double> allFrameRange;

    // this will eventually hold only the animated jobs.
    // its a list because we will be removing jobs from it
    std::list < AbcWriteJobPtr > jobList;

    for (unsigned int jobIndex = 0; jobIndex < jobSize; jobIndex++)
    {
        JobArgs jobArgs;
        MArgList jobArgList;
        argData.getFlagArgumentList("jobArg", jobIndex, jobArgList);
        MString jobArgsStr = jobArgList.asString(0);
        MStringArray jobArgsArray;

        {
            // parse the job arguments
            // e.g. -perFrameCallbackMel "print \"something\"" will be splitted to
            //    [0] -perFrameCallbackMel
            //    [1] print "something"
            enum State {
                kArgument,               // parsing an argument (not quoted)
                kDoubleQuotedString,     // parsing a double quoted string
                kSingleQuotedString,     // parsing a single quoted string
            };

            State state = kArgument;
            MString stringBuffer;
            for (unsigned int charIdx = 0; charIdx < jobArgsStr.numChars();
                charIdx++)
            {
                MString ch = jobArgsStr.substringW(charIdx, charIdx);
                switch (state)
                {
                case kArgument:
                    if (ch == " ")
                    {
                        // space terminates the current argument
                        if (stringBuffer.length() > 0) {
                            jobArgsArray.append(stringBuffer);
                            stringBuffer.clear();
                        }
                        // goto another argument
                        state = kArgument;
                    }
                    else if (ch == "\"")
                    {
                        if (stringBuffer.length() > 0)
                        {
                            // double quote is part of the argument
                            stringBuffer += ch;
                        }
                        else
                        {
                            // goto double quoted string
                            state = kDoubleQuotedString;
                        }
                    }
                    else if (ch == "'")
                    {
                        if (stringBuffer.length() > 0)
                        {
                            // single quote is part of the argument
                            stringBuffer += ch;
                        }
                        else
                        {
                            // goto single quoted string
                            state = kSingleQuotedString;
                        }
                    }
                    else
                    {
                        stringBuffer += ch;
                    }
                break;

                case kDoubleQuotedString:
                    // double quote terminates the current string
                    if (ch == "\"")
                    {
                        jobArgsArray.append(stringBuffer);
                        stringBuffer.clear();
                        state = kArgument;
                    }
                    else if (ch == "\\")
                    {
                        // escaped character
                        MString nextCh = (++charIdx < jobArgsStr.numChars())
                            ? jobArgsStr.substringW(charIdx, charIdx) : "\\";
                        if (nextCh == "n")       stringBuffer += "\n";
                        else if (nextCh == "t")  stringBuffer += "\t";
                        else if (nextCh == "r")  stringBuffer += "\r";
                        else if (nextCh == "\\") stringBuffer += "\\";
                        else if (nextCh == "'")  stringBuffer += "'";
                        else if (nextCh == "\"") stringBuffer += "\"";
                        else                     stringBuffer += nextCh;
                    }
                    else
                    {
                        stringBuffer += ch;
                    }
                break;

                case kSingleQuotedString:
                    // single quote terminates the current string
                    if (ch == "'")
                    {
                        jobArgsArray.append(stringBuffer);
                        stringBuffer.clear();
                        state = kArgument;
                    }
                    else if (ch == "\\")
                    {
                        // escaped character
                        MString nextCh = (++charIdx < jobArgsStr.numChars())
                            ? jobArgsStr.substringW(charIdx, charIdx) : "\\";
                        if (nextCh == "n")       stringBuffer += "\n";
                        else if (nextCh == "t")  stringBuffer += "\t";
                        else if (nextCh == "r")  stringBuffer += "\r";
                        else if (nextCh == "\\") stringBuffer += "\\";
                        else if (nextCh == "'")  stringBuffer += "'";
                        else if (nextCh == "\"") stringBuffer += "\"";
                        else                     stringBuffer += nextCh;
                    }
                    else
                    {
                        stringBuffer += ch;
                    }
                break;
                }
            }

            // the rest of the argument
            if (stringBuffer.length() > 0)
            {
                jobArgsArray.append(stringBuffer);
            }
        }

        // the frame range within this job
        std::vector< FrameRangeArgs > frameRanges(1);
        frameRanges.back().startTime = oldCurTime.value();
        frameRanges.back().endTime = oldCurTime.value();
        frameRanges.back().strideTime = 1.0;

        bool hasRange = false;
        bool hasRoot = false;
        bool sampleGeo  = true; // whether or not to subsample geometry
        std::string fileName;
        bool asOgawa = true;

        unsigned int numJobArgs = jobArgsArray.length();
        for (unsigned int i = 0; i < numJobArgs; ++i)
        {
            MString arg = jobArgsArray[i];
            arg.toLowerCase();

            if (arg == "-f" || arg == "-file")
            {
                if (i+1 >= numJobArgs)
                {
                    MGlobal::displayError("File incorrectly specified.");
                    return MS::kFailure;
                }
                fileName = jobArgsArray[++i].asChar();
            }

            else if (arg == "-fr" || arg == "-framerange")
            {
                if (i+2 >= numJobArgs || !jobArgsArray[i+1].isDouble() ||
                    !jobArgsArray[i+2].isDouble())
                {
                    MGlobal::displayError("Frame Range incorrectly specified.");
                    return MS::kFailure;
                }

                // this is not the first -frameRange argument, we are going
                // to add one more frame range to the frame range array.
                if (hasRange)
                {
                    frameRanges.push_back(FrameRangeArgs());
                }

                hasRange = true;
                frameRanges.back().startTime = jobArgsArray[++i].asDouble();
                frameRanges.back().endTime = jobArgsArray[++i].asDouble();

                // make sure start frame is smaller or equal to endTime
                if (frameRanges.back().startTime > frameRanges.back().endTime)
                {
                    std::swap(frameRanges.back().startTime,
                        frameRanges.back().endTime);
                }
            }

            else if (arg == "-frs" || arg == "-framerelativesample")
            {
                if (i+1 >= numJobArgs || !jobArgsArray[i+1].isDouble())
                {
                    MGlobal::displayError(
                        "Frame Relative Sample incorrectly specified.");
                    return MS::kFailure;
                }
                frameRanges.back().shutterSamples.insert(
                    jobArgsArray[++i].asDouble());
            }

            else if (arg == "-nn" || arg == "-nonormals")
            {
                jobArgs.noNormals = true;
            }

            else if (arg == "-pr" || arg == "-preroll")
            {
                frameRanges.back().preRoll = true;
            }

            else if (arg == "-ro" || arg == "-renderableonly")
            {
                jobArgs.excludeInvisible = true;
            }

            else if (arg == "-s" || arg == "-step")
            {
                if (i+1 >= numJobArgs || !jobArgsArray[i+1].isDouble())
                {
                    MGlobal::displayError("Step incorrectly specified.");
                    return MS::kFailure;
                }
                frameRanges.back().strideTime = jobArgsArray[++i].asDouble();
            }

            else if (arg == "-sl" || arg == "-selection")
            {
                jobArgs.useSelectionList = true;
            }

            else if (arg == "-sn" || arg == "-stripnamespaces")
            {
                if (i+1 >= numJobArgs || !jobArgsArray[i+1].isUnsigned())
                {
                    // the strip all namespaces case
                    // so we pick a very LARGE number
                    jobArgs.stripNamespace = 0xffffffff;
                }
                else
                {
                    jobArgs.stripNamespace = jobArgsArray[++i].asUnsigned();
                }
            }

            else if (arg == "-uv" || arg == "-uvwrite")
            {
                jobArgs.writeUVs = true;
            }

            else if (arg == "-wcs" || arg == "-writecolorsets")
            {
                jobArgs.writeColorSets = true;
            }

            else if (arg == "-wfs" || arg == "-writefacesets")
            {
                jobArgs.writeFaceSets = true;
            }

            else if (arg == "-wfg" || arg == "-wholeframegeo")
            {
                sampleGeo = false;
            }

            else if (arg == "-ws" || arg == "-worldspace")
            {
                jobArgs.worldSpace = true;
            }

            else if (arg == "-wv" || arg == "-writevisibility")
            {
                jobArgs.writeVisibility = true;
            }

            else if (arg == "-wc" || arg == "-writecreases")
            {
                jobArgs.writeCreases = true;
            }

            else if (arg == "-mfc" || arg == "-melperframecallback")
            {
                if (i+1 >= numJobArgs)
                {
                    MGlobal::displayError(
                        "melPerFrameCallback incorrectly specified.");
                    return MS::kFailure;
                }
                jobArgs.melPerFrameCallback = jobArgsArray[++i].asChar();
            }

            else if (arg == "-pfc" || arg == "-pythonperframecallback")
            {
                if (i+1 >= numJobArgs)
                {
                    MGlobal::displayError(
                        "pythonPerFrameCallback incorrectly specified.");
                    return MS::kFailure;
                }
                jobArgs.pythonPerFrameCallback = jobArgsArray[++i].asChar();
            }

            else if (arg == "-mpc" || arg == "-melpostjobcallback")
            {
                if (i+1 >= numJobArgs)
                {
                    MGlobal::displayError(
                        "melPostJobCallback incorrectly specified.");
                    return MS::kFailure;
                }
                jobArgs.melPostCallback = jobArgsArray[++i].asChar();
            }

            else if (arg == "-ppc" || arg == "-pythonpostjobcallback")
            {
                if (i+1 >= numJobArgs)
                {
                    MGlobal::displayError(
                        "pythonPostJobCallback incorrectly specified.");
                    return MS::kFailure;
                }
                jobArgs.pythonPostCallback = jobArgsArray[++i].asChar();
            }

            // geomArbParams - attribute filtering stuff
            else if (arg == "-atp" || arg == "-attrprefix")
            {
                if (i+1 >= numJobArgs)
                {
                    MGlobal::displayError(
                        "attrPrefix incorrectly specified.");
                    return MS::kFailure;
                }
                jobArgs.prefixFilters.push_back(jobArgsArray[++i].asChar());
            }

            else if (arg == "-a" || arg == "-attr")
            {
                if (i+1 >= numJobArgs)
                {
                    MGlobal::displayError(
                        "attr incorrectly specified.");
                    return MS::kFailure;
                }
                jobArgs.attribs.insert(jobArgsArray[++i].asChar());
            }

            // userProperties - attribute filtering stuff
            else if (arg == "-uatp" || arg == "-userattrprefix")
            {
                if (i+1 >= numJobArgs)
                {
                    MGlobal::displayError(
                        "userAttrPrefix incorrectly specified.");
                    return MS::kFailure;
                }
                jobArgs.userPrefixFilters.push_back(jobArgsArray[++i].asChar());
            }

            else if (arg == "-u" || arg == "-userattr")
            {
                if (i+1 >= numJobArgs)
                {
                    MGlobal::displayError(
                        "userAttr incorrectly specified.");
                    return MS::kFailure;
                }
                jobArgs.userAttribs.insert(jobArgsArray[++i].asChar());
            }

            else if (arg == "-rt" || arg == "-root")
            {
                if (i+1 >= numJobArgs)
                {
                    MGlobal::displayError(
                        "root incorrectly specified.");
                    return MS::kFailure;
                }
                hasRoot = true;
                MString root = jobArgsArray[++i];

                MSelectionList sel;
                if (sel.add(root) != MS::kSuccess)
                {
                    MString warn = root;
                    warn += " could not be select, skipping.";
                    MGlobal::displayWarning(warn);
                    continue;
                }

                unsigned int numRoots = sel.length();
                for (unsigned int j = 0; j < numRoots; ++j)
                {
                    MDagPath path;
                    if (sel.getDagPath(j, path) != MS::kSuccess)
                    {
                        MString warn = path.fullPathName();
                        warn += " (part of ";
                        warn += root;
                        warn += " ) not a DAG Node, skipping.";
                        MGlobal::displayWarning(warn);
                        continue;
                    }
                    jobArgs.dagPaths.insert(path);
                }
            }
            else if (arg == "-ef" || arg == "-eulerfilter")
            {
                jobArgs.filterEulerRotations = true;
            }
            else if (arg == "-df" || arg == "-dataformat")
            {
                if (i+1 >= numJobArgs)
                {
                    MGlobal::displayError(
                        "dataFormat incorrectly specified.");
                    return MS::kFailure;
                }
                MString dataFormat = jobArgsArray[++i];
                dataFormat.toLowerCase();
                if (dataFormat == "hdf")
                {
                    asOgawa = false;
                }
                else if (dataFormat == "ogawa")
                {
                    asOgawa = true;
                }
            }
            else
            {
                MString warn = "Ignoring unsupported flag: ";
                warn += jobArgsArray[i];
                MGlobal::displayWarning(warn);
            }
        } //  for i

        if (fileName == "")
        {
            MString error = "-file not specified.";
            MGlobal::displayError(error);
            return MS::kFailure;
        }

        {
            MString fileRule, expandName;
            MString alembicFileRule = "alembicCache";
            MString alembicFilePath = "cache/alembic";

            MString queryFileRuleCmd;
            queryFileRuleCmd.format("workspace -q -fre \"^1s\"",
                alembicFileRule);

            MString queryFolderCmd;
            queryFolderCmd.format("workspace -en `workspace -q -fre \"^1s\"`",
                alembicFileRule);

            // query the file rule for alembic cache
            MGlobal::executeCommand(queryFileRuleCmd, fileRule);
            if (fileRule.length() > 0)
            {
                // we have alembic file rule, query the folder
                MGlobal::executeCommand(queryFolderCmd, expandName);
            }
            else
            {
                // alembic file rule does not exist, create it
                MString addFileRuleCmd;
                addFileRuleCmd.format("workspace -fr \"^1s\" \"^2s\"",
                    alembicFileRule, alembicFilePath);
                MGlobal::executeCommand(addFileRuleCmd);

                // save the workspace. maya may discard file rules on exit
                MGlobal::executeCommand("workspace -s");

                // query the folder
                MGlobal::executeCommand(queryFolderCmd, expandName);
            }

            // resolve the expanded file rule
            if (expandName.length() == 0)
            {
                expandName = alembicFilePath;
            }

            // get the path to the alembic file rule
            MFileObject directory;
            directory.setRawFullName(expandName);
            MString directoryName = directory.resolvedFullName();

            // make sure the cache folder exists
            if (!directory.exists())
            {
                // create the cache folder
                MString createFolderCmd;
                createFolderCmd.format("sysFile -md \"^1s\"", directoryName);
                MGlobal::executeCommand(createFolderCmd);
            }

            // resolve the relative path
            MFileObject absoluteFile;
            absoluteFile.setRawFullName(fileName.c_str());
#if MAYA_API_VERSION < 201300
            if (absoluteFile.resolvedFullName() !=
                absoluteFile.expandedFullName())
            {
#else
            if (!MFileObject::isAbsolutePath(fileName.c_str())) {
#endif
                // this is a relative path
                MString absoluteFileName = directoryName + "/" +
                    fileName.c_str();
                absoluteFile.setRawFullName(absoluteFileName);
                fileName = absoluteFile.resolvedFullName().asChar();
            }
            else
            {
                fileName = absoluteFile.resolvedFullName().asChar();
            }

            // check the path must exist before writing
            MFileObject absoluteFilePath;
            absoluteFilePath.setRawFullName(absoluteFile.path());
            if (!absoluteFilePath.exists()) {
                MString error;
                error.format("Path ^1s does not exist!", absoluteFilePath.resolvedFullName());
                MGlobal::displayError(error);
                return MS::kFailure;
            }

            // check the file is used by any AlembicNode in the scene
            MItDependencyNodes dgIter(MFn::kPluginDependNode);
            for (; !dgIter.isDone(); dgIter.next()) {
                MFnDependencyNode alembicNode(dgIter.thisNode());
                if (alembicNode.typeName() != "AlembicNode") {
                    continue;
                }

                MPlug abcFilePlug = alembicNode.findPlug("abc_File");
                if (abcFilePlug.isNull()) {
                    continue;
                }

                MFileObject alembicFile;
                alembicFile.setRawFullName(abcFilePlug.asString());
                if (!alembicFile.exists()) {
                    continue;
                }

                if (alembicFile.resolvedFullName() == absoluteFile.resolvedFullName()) {
                    MString error = "Can't export to an Alembic file which is in use.";
                    MGlobal::displayError(error);
                    return MS::kFailure;
                }
            }

            std::ofstream ofs(fileName.c_str());
            if (!ofs.is_open()) {
                MString error = MString("Can't write to file: ") + fileName.c_str();
                MGlobal::displayError(error);
                return MS::kFailure;
            }
            ofs.close();
        }

        // if -frameRelativeSample argument is not specified for a frame range,
        // we are assuming a -frameRelativeSample 0.0
        for (std::vector<FrameRangeArgs>::iterator range =
            frameRanges.begin(); range != frameRanges.end(); ++range)
        {
            if (range->shutterSamples.empty())
                range->shutterSamples.insert(0.0);
        }

        if (jobArgs.prefixFilters.empty())
        {
            jobArgs.prefixFilters.push_back("ABC_");
        }

        // the list of frame ranges for sampling
        std::vector<FrameRangeArgs> sampleRanges;
        std::vector<FrameRangeArgs> preRollRanges;
        for (std::vector<FrameRangeArgs>::const_iterator range =
            frameRanges.begin(); range != frameRanges.end(); ++range)
        {
            if (range->preRoll)
                preRollRanges.push_back(*range);
            else
                sampleRanges.push_back(*range);
        }

        // the list of frames written into the abc file
        std::set<double> geoSamples;
        std::set<double> transSamples;
        for (std::vector<FrameRangeArgs>::const_iterator range =
            sampleRanges.begin(); range != sampleRanges.end(); ++range)
        {
            for (double frame = range->startTime;
                frame <= range->endTime;
                frame += range->strideTime)
            {
                for (std::set<double>::const_iterator shutter =
                    range->shutterSamples.begin();
                    shutter != range->shutterSamples.end(); ++shutter)
                {
                    double curFrame = *shutter + frame;
                    if (!sampleGeo)
                    {
                        double intFrame = (double)(int)(
                            curFrame >= 0 ? curFrame + .5 : curFrame - .5);

                        // only insert samples that are close to being an integer
                        if (fabs(curFrame - intFrame) < 1e-4)
                        {
                            geoSamples.insert(curFrame);
                        }
                    }
                    else
                    {
                        geoSamples.insert(curFrame);
                    }
                    transSamples.insert(curFrame);
                }
            }

            if (geoSamples.empty())
            {
                geoSamples.insert(range->startTime);
            }

            if (transSamples.empty())
            {
                transSamples.insert(range->startTime);
            }
        }

        bool isAcyclic = false;
        if (sampleRanges.empty())
        {
            // no frame ranges or all frame ranges are pre-roll ranges
            hasRange = false;
            geoSamples.insert(frameRanges.back().startTime);
            transSamples.insert(frameRanges.back().startTime);
        }
        else
        {
            // check if the time range is even (cyclic)
            // otherwise, we will use acyclic
            // sub frames pattern
            std::vector<double> pattern(
                sampleRanges.begin()->shutterSamples.begin(),
                sampleRanges.begin()->shutterSamples.end());
            std::transform(pattern.begin(), pattern.end(), pattern.begin(),
                std::bind2nd(std::plus<double>(),
                    sampleRanges.begin()->startTime));

            // check the frames against the pattern
            std::vector<double> timeSamples(
                transSamples.begin(), transSamples.end());
            for (size_t i = 0; i < timeSamples.size(); i++)
            {
                // next pattern
                if (i % pattern.size() == 0 && i / pattern.size() > 0)
                {
                    std::transform(pattern.begin(), pattern.end(),
                        pattern.begin(), std::bind2nd(std::plus<double>(),
                            sampleRanges.begin()->strideTime));
                }

                // pattern mismatch, we use acyclic time sampling type
                if (timeSamples[i] != pattern[i % pattern.size()])
                {
                    isAcyclic = true;
                    break;
                }
            }
        }

        // the list of frames to pre-roll
        std::set<double> preRollSamples;
        for (std::vector<FrameRangeArgs>::const_iterator range =
            preRollRanges.begin(); range != preRollRanges.end(); ++range)
        {
            for (double frame = range->startTime;
                frame <= range->endTime;
                frame += range->strideTime)
            {
                for (std::set<double>::const_iterator shutter =
                    range->shutterSamples.begin();
                    shutter != range->shutterSamples.end(); ++shutter)
                {
                    double curFrame = *shutter + frame;
                    preRollSamples.insert(curFrame);
                }
            }

            if (preRollSamples.empty())
            {
                preRollSamples.insert(range->startTime);
            }
        }

        if (jobArgs.dagPaths.size() > 1)
        {
            // check for validity of the DagPath relationships complexity : n^2

            util::ShapeSet::const_iterator m, n;
            util::ShapeSet::const_iterator end = jobArgs.dagPaths.end();
            for (m = jobArgs.dagPaths.begin(); m != end; )
            {
                MDagPath path1 = *m;
                m++;
                for (n = m; n != end; n++)
                {
                    MDagPath path2 = *n;
                    if (util::isAncestorDescendentRelationship(path1,path2))
                    {
                        MString errorMsg = path1.fullPathName();
                        errorMsg += " and ";
                        errorMsg += path2.fullPathName();
                        errorMsg += " have an ancestor relationship.";
                        MGlobal::displayError(errorMsg);
                        return MS::kFailure;
                    }
                }  // for n
            }  // for m
        }
        // no root is specified, and we aren't using a selection
        // so we'll try to translate the whole Maya scene by using all
        // children of the world as roots.
        else if (!hasRoot && !jobArgs.useSelectionList)
        {
            MSelectionList sel;
#if MAYA_API_VERSION >= 201100
            sel.add("|*", true);
#else
            // older versions of Maya will not be able to find top level nodes
            // within namespaces
            sel.add("|*");
#endif
            unsigned int numRoots = sel.length();
            for (unsigned int i = 0; i < numRoots; ++i)
            {
                MDagPath path;
                sel.getDagPath(i, path);
                jobArgs.dagPaths.insert(path);
            }
        }
        else if (hasRoot && jobArgs.dagPaths.empty())
        {
            MString errorMsg = "No valid root nodes were specified.";
            MGlobal::displayError(errorMsg);
            return MS::kFailure;
        }
        else if (jobArgs.useSelectionList)
        {
            MSelectionList activeList;
            MGlobal::getActiveSelectionList(activeList);
            if (activeList.length() == 0)
            {
                MString errorMsg =
                    "-selection specified but nothing is actively selected.";
                MGlobal::displayError(errorMsg);
                return MS::kFailure;
            }
        }

        AbcA::TimeSamplingPtr transTime, geoTime;

        if (hasRange)
        {
            if (isAcyclic)
            {
                // acyclic, uneven time sampling
                // e.g. [0.8, 1, 1.2], [2.8, 3, 3.2], .. not continuous
                //      [0.8, 1, 1.2], [1.7, 2, 2.3], .. shutter different
                std::vector<double> samples(
                    transSamples.begin(), transSamples.end());
                std::transform(samples.begin(), samples.end(), samples.begin(),
                    std::bind2nd(std::multiplies<double>(), util::spf()));
                transTime.reset(new AbcA::TimeSampling(AbcA::TimeSamplingType(
                    AbcA::TimeSamplingType::kAcyclic), samples));
            }
            else
            {
                // cyclic, even time sampling between time periods
                // e.g. [0.8, 1, 1.2], [1.8, 2, 2.2], ...
                std::vector<double> samples;
                double startTime = sampleRanges[0].startTime;
                double strideTime = sampleRanges[0].strideTime;
                for (std::set<double>::const_iterator shutter =
                    sampleRanges[0].shutterSamples.begin();
                    shutter != sampleRanges[0].shutterSamples.end();
                    ++shutter)
                {
                    samples.push_back((startTime + *shutter) * util::spf());
                }

                if (samples.size() > 1)
                {
                    Alembic::Util::uint32_t numSamples =
                        static_cast<Alembic::Util::uint32_t>(samples.size());
                    transTime.reset(
                        new AbcA::TimeSampling(AbcA::TimeSamplingType(
                            numSamples, strideTime * util::spf()), samples));
                }
                // uniform sampling
                else
                {
                    transTime.reset(new AbcA::TimeSampling(
                        strideTime * util::spf(), samples[0]));
                }
            }
        }
        else
        {
            // time ranges are not specified
            transTime.reset(new AbcA::TimeSampling());
        }

        if (sampleGeo || !hasRange)
        {
            geoTime = transTime;
        }
        else
        {
            // sampling geo on whole frames
            if (isAcyclic)
            {
                // acyclic, uneven time sampling
                std::vector<double> samples(
                    geoSamples.begin(), geoSamples.end());
                // one more sample for setup()
                if (*transSamples.begin() != *geoSamples.begin())
                    samples.insert(samples.begin(), *transSamples.begin());
                std::transform(samples.begin(), samples.end(), samples.begin(),
                    std::bind2nd(std::multiplies<double>(), util::spf()));
                geoTime.reset(new AbcA::TimeSampling(AbcA::TimeSamplingType(
                    AbcA::TimeSamplingType::kAcyclic), samples));
            }
            else
            {
                double geoStride = sampleRanges[0].strideTime;
                if (geoStride < 1.0)
                    geoStride = 1.0;

                double geoStart = *geoSamples.begin() * util::spf();
                geoTime.reset(new AbcA::TimeSampling(
                    geoStride * util::spf(), geoStart));
            }
        }

        AbcWriteJobPtr job(new AbcWriteJob(fileName.c_str(), asOgawa,
            transSamples, transTime, geoSamples, geoTime, jobArgs));

       jobList.push_front(job);

        // make sure we add additional whole frames, if we arent skipping
        // the inbetween ones
        if (!skipFrame && !allFrameRange.empty())
        {
            double localMin = *(transSamples.begin());
            std::set<double>::iterator last = transSamples.end();
            last--;
            double localMax = *last;

            double globalMin = *(allFrameRange.begin());
            last = allFrameRange.end();
            last--;
            double globalMax = *last;

            // if the min of our current frame range is beyond
            // what we know about, pad a few more frames
            if (localMin > globalMax)
            {
                for (double f = globalMax; f < localMin; f++)
                {
                    allFrameRange.insert(f);
                }
            }

            // if the max of our current frame range is beyond
            // what we know about, pad a few more frames
            if (localMax < globalMin)
            {
                for (double f = localMax; f < globalMin; f++)
                {
                    allFrameRange.insert(f);
                }
            }
        }

        // right now we just copy over the translation samples since
        // they are guaranteed to contain all the geometry samples
        allFrameRange.insert(transSamples.begin(), transSamples.end());

        // copy over the pre-roll samples
        allFrameRange.insert(preRollSamples.begin(), preRollSamples.end());
    }

    // add extra evaluation run up, if necessary
    if (startEvaluationTime != DBL_MAX && !allFrameRange.empty())
    {
        double firstFrame = *allFrameRange.begin();
        for (double f = startEvaluationTime; f < firstFrame; ++f)
        {
            allFrameRange.insert(f);
        }
    }

    std::set<double>::iterator it = allFrameRange.begin();
    std::set<double>::iterator itEnd = allFrameRange.end();

    MComputation computation;
    computation.beginComputation();

    // loop through every frame in the list, if a job has that frame in it's
    // list of transform or shape frames, then it will write out data and
    // call the perFrameCallback, if that frame is also the last one it has
    // to work on then it will also call the postCallback.
    // If it doesn't have this frame, then it does nothing
    for (; it != itEnd; it++)
    {
        if (verbose)
        {
            double frame = *it;
            MString info;
            info = frame;
            MGlobal::displayInfo(info);
        }

        MGlobal::viewFrame(*it);
        std::list< AbcWriteJobPtr >::iterator j = jobList.begin();
        std::list< AbcWriteJobPtr >::iterator jend = jobList.end();
        while (j != jend)
        {
            if (computation.isInterruptRequested())
                return MS::kFailure;

            bool lastFrame = (*j)->eval(*it);

            if (lastFrame)
            {
                j = jobList.erase(j);
            }
            else
                j++;
        }
    }
    computation.endComputation();

    // set the time back
    MGlobal::viewFrame(oldCurTime);

    return MS::kSuccess;
}
catch (Alembic::Util::Exception & e)
{
    MString theError("Alembic Exception encountered: ");
    theError += e.what();
    MGlobal::displayError(theError);
    return MS::kFailure;
}
catch (std::exception & e)
{
    MString theError("std::exception encountered: ");
    theError += e.what();
    MGlobal::displayError(theError);
    return MS::kFailure;
}

}
MStatus ClassParameterHandler::doUpdate( IECore::ConstParameterPtr parameter, MPlug &plug ) const
{
	if( !parameter || !parameter->isInstanceOf( IECore::ClassParameterTypeId ) )
	{
		return MS::kFailure;
	}

	MObject attribute = plug.attribute();
	// compatibility for the deprecated compound plug behaviour: should return MS::kFailure
	MFnTypedAttribute fnTAttr( attribute );
	if ( !fnTAttr.hasObj( attribute ) || fnTAttr.attrType() != MFnData::kStringArray )
	{
		MFnCompoundAttribute fnCAttr( attribute );
		if( !fnCAttr.hasObj( attribute ) )
		{
			return MS::kFailure;
		}
		
		if( fnCAttr.numChildren()!=3 )
		{
			return MS::kFailure;
		}
		
		MObject classNameAttr = fnCAttr.child( 0 );
		MFnTypedAttribute fnTAttr( classNameAttr );
		if( !fnTAttr.hasObj( classNameAttr ) )
		{
			return MS::kFailure;	
		}
		if( fnTAttr.name() != fnCAttr.name() + "__className" )
		{
			return MS::kFailure;
		}
		if( fnTAttr.attrType()!=MFnData::kString )
		{
			return MS::kFailure;
		}
		
		MObject classVersionAttr = fnCAttr.child( 1 );
		MFnNumericAttribute fnNAttr( classVersionAttr );
		if( !fnNAttr.hasObj( classVersionAttr ) )
		{
			return MS::kFailure;
		}
		if( fnNAttr.name() != fnCAttr.name() + "__classVersion" )
		{
			return MS::kFailure;
		}
		if( fnNAttr.unitType() != MFnNumericData::kInt )
		{
			return MS::kFailure;
		}
		
		MObject searchPathEnvVarAttr = fnCAttr.child( 2 );
		fnTAttr.setObject( searchPathEnvVarAttr );
		if( !fnTAttr.hasObj( searchPathEnvVarAttr ) )
		{
			return MS::kFailure;	
		}
		if( fnTAttr.name() != fnCAttr.name() + "__searchPathEnvVar" )
		{
			return MS::kFailure;
		}
		if( fnTAttr.attrType()!=MFnData::kString )
		{
			return MS::kFailure;
		}
		
		if( !storeClass( parameter, plug ) )
		{
			return MS::kFailure;
		}
	}
	
	if( !storeClass( parameter, plug ) )
	{
		return MS::kFailure;
	}
	
	return finishUpdating( parameter, plug );
}
Example #29
0
MStatus splineSolverNode::preSolve()
{

    MStatus stat;
    setRotatePlane(false);
    setSingleChainOnly(true);
    setPositionOnly(false);
    //Get Handle
    MIkHandleGroup * handle_group = handleGroup();
    if (NULL == handle_group) {
        return MS::kFailure;
    }
    MObject handle = handle_group->handle( 0 );
    MDagPath handlePath = MDagPath::getAPathTo( handle );
    fnHandle.setObject( handlePath );
    //Get Curve
    MPlug inCurvePlug = fnHandle.findPlug( "inCurve" );
    MDataHandle curveHandle = inCurvePlug.asMDataHandle();
    MObject inputCurveObject = curveHandle.asNurbsCurveTransformed();
    curveFn.setObject( inputCurveObject );
    float initCurveLength = curveFn.length();
    MVector initNormal = curveFn.normal(0);
    MVector initTangent = curveFn.tangent(0);
    float stretchRatio = 1;
    // Get the position of the end_effector
    //
    MDagPath effectorPath;
    fnHandle.getEffector(effectorPath);
    tran.setObject( effectorPath );
    // Get the start joint position
    //
    MDagPath startJointPath;
    fnHandle.getStartJoint( startJointPath );
    joints.clear();
    //Get Joints
    while (true)
    {
        effectorPath.pop();
        joints.push_back( effectorPath );
        if (effectorPath == startJointPath)
            break;
    }
    std::reverse(joints.begin(), joints.end());
    if (!fnHandle.hasAttribute("str"))
    {
        //Add Custom Attributes to Handle
        MFnNumericAttribute fnAttr;
        MObject attr = fnAttr.create("stretchRatio", "str", MFnNumericData::kDouble, stretchRatio);
        fnAttr.setKeyable(1);
        fnAttr.setWritable(1);
        fnAttr.setMin(0);
        fnAttr.setMax(1);
        fnAttr.setHidden(0);
        fnAttr.setStorable(1);
        fnAttr.setReadable(1);
        fnHandle.addAttribute(attr, MFnDependencyNode::kLocalDynamicAttr);
        attr = fnAttr.create("anchorPosition", "ancp", MFnNumericData::kDouble, 0.0);
        fnAttr.setKeyable(1);
        fnAttr.setWritable(1);
        fnAttr.setMin(0);
        fnAttr.setMax(1);
        fnAttr.setHidden(0);
        fnAttr.setStorable(1);
        fnAttr.setReadable(1);
        fnHandle.addAttribute(attr, MFnDependencyNode::kLocalDynamicAttr);
        attr = fnAttr.create("curveLength", "cvLen", MFnNumericData::kDouble, initCurveLength);
        fnAttr.setKeyable(0);
        fnAttr.setWritable(1);
        fnAttr.setHidden(1);
        fnAttr.setStorable(1);
        fnAttr.setReadable(1);
        fnHandle.addAttribute(attr, MFnDependencyNode::kLocalDynamicAttr);
        attr = fnAttr.create("initNormal", "norm", MFnNumericData::k3Double);
        fnAttr.setDefault(initNormal.x, initNormal.y, initNormal.z);
        fnAttr.setKeyable(0);
        fnAttr.setWritable(1);
        fnAttr.setHidden(1);
        fnAttr.setStorable(1);
        fnAttr.setReadable(1);
        fnHandle.addAttribute(attr, MFnDependencyNode::kLocalDynamicAttr);
        attr = fnAttr.create("initTangent", "tang", MFnNumericData::k3Double);
        fnAttr.setDefault(initTangent.x, initTangent.y, initTangent.z);
        fnAttr.setKeyable(0);
        fnAttr.setWritable(1);
        fnAttr.setHidden(1);
        fnAttr.setStorable(1);
        fnAttr.setReadable(1);
        fnHandle.addAttribute(attr, MFnDependencyNode::kLocalDynamicAttr);
        attr = fnAttr.create("jointsLength", "jsLen", MFnNumericData::kDouble, getJointsTotalLenght());
        fnAttr.setKeyable(0);
        fnAttr.setWritable(1);
        fnAttr.setHidden(1);
        fnAttr.setStorable(1);
        fnAttr.setReadable(1);
        fnHandle.addAttribute(attr, MFnDependencyNode::kLocalDynamicAttr);
        attr = fnAttr.create("startTwist", "strtw", MFnNumericData::kDouble, 0.0);
        fnAttr.setKeyable(1);
        fnAttr.setWritable(1);
        fnAttr.setHidden(0);
        fnAttr.setStorable(1);
        fnAttr.setReadable(1);
        fnHandle.addAttribute(attr, MFnDependencyNode::kLocalDynamicAttr);
        attr = fnAttr.create("endTwist", "endtw", MFnNumericData::kDouble, 0.0);
        fnAttr.setKeyable(1);
        fnAttr.setWritable(1);
        fnAttr.setHidden(0);
        fnAttr.setStorable(1);
        fnAttr.setReadable(1);
        fnHandle.addAttribute(attr, MFnDependencyNode::kLocalDynamicAttr);
        MObject twistRamp = MRampAttribute::createCurveRamp("twistRamp", "twr");
        fnHandle.addAttribute(twistRamp, MFnDependencyNode::kLocalDynamicAttr);
        MObject scaleRamp = MRampAttribute::createCurveRamp("scaleRamp", "scr");
        fnHandle.addAttribute(scaleRamp, MFnDependencyNode::kLocalDynamicAttr);
    } else
    {
        MPlug strPlug = fnHandle.findPlug("str");
        stretchRatio = strPlug.asDouble();
    }

    return MS::kSuccess;
}
//------------------------------------------------------------------------------
//
bool LocatorRepresentation::activate()
{
   MPxAssembly* const assembly = getAssembly();

   // Create a locator node, and parent it to our container.
   MDagModifier dagMod;
   MStatus status;
   dagMod.createNode(MString("locator"), assembly->thisMObject(), &status);   
  
   if (status != MStatus::kSuccess) {
      return false;
   }
   status = dagMod.doIt();
   if (status != MStatus::kSuccess) {
      return false;
   }

   // If we have annotation text, create an annotation shape, and a
   // transform for it.  Parent the annotation transform to the assembly.
   if (fAnnotation.numChars() > 0) {
      MObject transformObj = dagMod.createNode(
         MString("transform"), assembly->thisMObject(), &status);

      if (status != MStatus::kSuccess) {
         return false;
      }

	  MString  annotationName =  "annotation";
	  // the + "#" forces Maya to rename using integers for unique names
	  MString  transformName = annotationName + "#";
      dagMod.renameNode(transformObj, transformName);
 
      status = dagMod.doIt();
      if (status != MStatus::kSuccess) {
         return false;
      }

      MObject annotationObj = dagMod.createNode(
         MString("annotationShape"), transformObj, &status);

      if (status != MStatus::kSuccess) {
         return false;
      }
      status = dagMod.doIt();
      if (status != MStatus::kSuccess) {
         return false;
      }

      // Set the annotation text.
      MFnDependencyNode annotation(annotationObj);
      MPlug text = annotation.findPlug(MString("text"), true, &status);
      if (status != MStatus::kSuccess) {
         return false;
      }
      text.setValue(fAnnotation);

      // Get rid of the arrow: our annotation doesn't need to be
      // offset from the locator for readability, since the locator
      // has no volume.  Therefore, we don't need an arrow to point
      // from the annotation back to the object.
      MPlug displayArrow =
         annotation.findPlug(MString("displayArrow"), true, &status);
      if (status != MStatus::kSuccess) {
         return false;
      }
      displayArrow.setValue(false);
   }
   
   return status == MStatus::kSuccess;
}