Esempio n. 1
0
MStatus VoxelShape::compute( const MPlug& plug, MDataBlock& data ) {
	MStatus stat;

	// Check which output attribute we have been asked to compute.  If this 
	// node doesn't know how to compute it, we must return 
	// MS::kUnknownParameter.
	// 
	if( plug == outData )
	{
		// Get a handle to the input attribute that we will need for the
		// computation.  If the value is being supplied via a connection 
		// in the dependency graph, then this call will cause all upstream  
		// connections to be evaluated so that the correct value is supplied.
		// 
		MDataHandle inputDataHandle = data.inputValue( voxelData, &stat );

		MObject inputDataObj = inputDataHandle.data();
		
		MFnPluginData fnDataCreator;
		MTypeId tmpid( VoxelPreviewDataWrapper::id );
		VoxelPreviewDataWrapper * newData = NULL;

		MDataHandle outHandle = data.outputValue( outData );	
		newData = (VoxelPreviewDataWrapper*)outHandle.asPluginData();

		if ( newData == NULL ) {
			// Create some output data
			fnDataCreator.create( tmpid, &stat );
			MCHECKERROR( stat, "compute : error creating VoxelPreviewDataWrapper")
				newData = (VoxelPreviewDataWrapper*)fnDataCreator.data( &stat );
			MCHECKERROR( stat, "compute : error getting proxy VoxelPreviewDataWrapper object")
		}
MStatus NeuronForMayaDevice::createOculusAttribute( MObject& obj, MObject& objX, MObject& objY, MObject& objZ, const MString& longName, const MString& shortName, bool hidden )
{
    MStatus status;
    MFnNumericAttribute numAttr;

    objX = numAttr.create( longName+"X", shortName+"X", MFnNumericData::kDouble, 0.0, &status);
    MCHECKERROR(status, "create " + longName+"X");
    objY = numAttr.create( longName+"Y", shortName+"Y", MFnNumericData::kDouble, 0.0, &status);
    MCHECKERROR(status, "create " + longName+"Y");
    objZ = numAttr.create( longName+"Z", shortName+"Z", MFnNumericData::kDouble, 0.0, &status);
    MCHECKERROR(status, "create " + longName+"Z");

    obj = numAttr.create(longName, shortName, objX, objY, objZ, &status);
    MCHECKERROR(status, "create "+ longName);
    numAttr.setHidden(hidden);

    ADD_ATTRIBUTE(obj);

    return MS::kSuccess;
}
MStatus NeuronForMayaDevice::compute( const MPlug& plug, MDataBlock& block )
{
    MStatus status;
    if( plug == outputTranslate || plug == outputTranslateX || plug == outputTranslateY || plug == outputTranslateZ 
        || plug == outputLeftCameraPosition || plug == outputLeftCameraPositionX || plug == outputLeftCameraPositionY || plug == outputLeftCameraPositionZ
        || plug == outputLeftCameraRotation || plug == outputLeftCameraRotationX || plug == outputLeftCameraRotationY || plug == outputLeftCameraRotationZ
        || plug == outputRightCameraPosition || plug == outputRightCameraPositionX || plug == outputRightCameraPositionY || plug == outputRightCameraPositionZ
        || plug == outputRightCameraRotation || plug == outputRightCameraRotationX || plug == outputRightCameraRotationY || plug == outputRightCameraRotationZ
        )
    {
        MCharBuffer buffer;
        if ( popThreadData(buffer) )
        {
            double* doubleData = reinterpret_cast<double*>(buffer.ptr());

            int i = 0;
            MDataHandle outputLeftCameraPositionHandle = block.outputValue( outputLeftCameraPosition, &status );
            MCHECKERROR(status, "Error in block.outputValue for outputLeftCameraPosition");

            double3& outputLeftCameraPosition = outputLeftCameraPositionHandle.asDouble3();
            outputLeftCameraPosition[0] = doubleData[i++];
            outputLeftCameraPosition[1] = doubleData[i++];
            outputLeftCameraPosition[2] = doubleData[i++];


            MDataHandle outputLeftCameraRotationHandle = block.outputValue( outputLeftCameraRotation, &status );
            MCHECKERROR(status, "Error in block.outputValue for outputLeftCameraRotation");

            double3& outputLeftCameraRotation = outputLeftCameraRotationHandle.asDouble3();
            outputLeftCameraRotation[0] = doubleData[i++];
            outputLeftCameraRotation[1] = doubleData[i++];
            outputLeftCameraRotation[2] = doubleData[i++];


            MDataHandle outputRightCameraPositionHandle = block.outputValue( outputRightCameraPosition, &status );
            MCHECKERROR(status, "Error in block.outputValue for outputRightCameraPosition");

            double3& outputRightCameraPosition = outputRightCameraPositionHandle.asDouble3();
            outputRightCameraPosition[0] = doubleData[i++];
            outputRightCameraPosition[1] = doubleData[i++];
            outputRightCameraPosition[2] = doubleData[i++];

            MDataHandle outputRightCameraRotationHandle = block.outputValue( outputRightCameraRotation, &status );
            MCHECKERROR(status, "Error in block.outputValue for outputRightCameraRotation");

            double3& outputRightCameraRotation = outputRightCameraRotationHandle.asDouble3();
            outputRightCameraRotation[0] = doubleData[i++];
            outputRightCameraRotation[1] = doubleData[i++];
            outputRightCameraRotation[2] = doubleData[i++];


            MDataHandle outputTranslateHandle = block.outputValue( outputTranslate, &status );
            MCHECKERROR(status, "Error in block.outputValue for outputTranslate");

            double3& outputTranslate = outputTranslateHandle.asDouble3();
            outputTranslate[0] = doubleData[i++];
            outputTranslate[1] = doubleData[i++];
            outputTranslate[2] = doubleData[i++];

            block.setClean( plug );

            releaseDataStorage(buffer);
            return ( MS::kSuccess );
        }
        else
        {
            return MS::kFailure;
        }
    }

    return ( MS::kUnknownParameter );
}
Esempio n. 4
0
// DESCRIPTION:
//
MStatus PtexColorNode::initialize()
{
	MStatus status;

	MFnNumericAttribute numericAttribute;

	// Input attributes

	MFnTypedAttribute fileNameAttribute;
	aPtexFileName = fileNameAttribute.create( "ptexFileName", "f", MFnData::kString );
	MAKE_INPUT( fileNameAttribute );
	fileNameAttribute.setConnectable(false);

	MFnEnumAttribute enumAttribute;
	aPtexFilterType = enumAttribute.create( "ptexFilterType", "t", 0, &status );
	MCHECKERROR( status, "create filterType attribute" );
	enumAttribute.addField( "Point",      0 );
	enumAttribute.addField( "Bilinear",   1 );
	enumAttribute.addField( "Box",        2 );
	enumAttribute.addField( "Gaussian",   3 );
	enumAttribute.addField( "Bicubic",    4 );
	enumAttribute.addField( "BSpline",    5 );
	enumAttribute.addField( "CatmullRom", 6 );
	enumAttribute.addField( "Mitchell",   7 );
	enumAttribute.setHidden( false );
	MAKE_INPUT( enumAttribute );
	enumAttribute.setConnectable(false);
	MCHECKERROR( status, "Error adding shapeType attribute." );

	MFnNumericAttribute filterSizeAttribute;
	aPtexFilterSize = filterSizeAttribute.create( "ptexFilterSize", "s", MFnNumericData::kFloat, 1.0 );
	MAKE_INPUT( filterSizeAttribute );
	filterSizeAttribute.setConnectable(false);

	// Implicit shading network attributes

	MObject child1 = numericAttribute.create( "uCoord", "u", MFnNumericData::kFloat);
	MObject child2 = numericAttribute.create( "vCoord", "v", MFnNumericData::kFloat);
	aUVPos = numericAttribute.create( "uvCoord", "uv", child1, child2);
	MAKE_INPUT( numericAttribute );
	CHECK_MSTATUS( numericAttribute.setHidden(true) );

	child1 = numericAttribute.create( "uvFilterSizeX", "fsx", MFnNumericData::kFloat);
	child2 = numericAttribute.create( "uvFilterSizeY", "fsy", MFnNumericData::kFloat);
	aUVSize = numericAttribute.create( "uvFilterSize", "fs", child1, child2 );
	MAKE_INPUT( numericAttribute );
	CHECK_MSTATUS( numericAttribute.setHidden(true) );

	// Output attributes
	aOutColor = numericAttribute.createColor("outColor", "oc");
	MAKE_OUTPUT(numericAttribute);

	// Add attributes to the node database.
	CHECK_MSTATUS( addAttribute(aPtexFileName) );
	CHECK_MSTATUS( addAttribute(aPtexFilterType) );
	CHECK_MSTATUS( addAttribute(aPtexFilterSize) );
	CHECK_MSTATUS( addAttribute(aUVPos) );
	CHECK_MSTATUS( addAttribute(aUVSize) );

	CHECK_MSTATUS( addAttribute(aOutColor) );

	// All input affect the output color
	CHECK_MSTATUS( attributeAffects( aPtexFileName,   aOutColor ) );
	CHECK_MSTATUS( attributeAffects( aPtexFilterSize, aOutColor ) );
	CHECK_MSTATUS( attributeAffects( aPtexFilterType, aOutColor ) );
	CHECK_MSTATUS( attributeAffects( aUVPos,          aOutColor ) );
	CHECK_MSTATUS( attributeAffects( aUVSize,         aOutColor ) );

	return MS::kSuccess;
}
MStatus NuiMayaDeviceGrabber::compute( const MPlug& plug, MDataBlock& datablock )
//
//	Description:
//		This method computes the value of the given output plug based
//		on the values of the input attributes.
//
//	Arguments:
//		plug - the plug to compute
//		data - object that provides access to the attributes for this node
//
{
	assert(m_pCache);
	if(!m_pCache)
		return MS::kFailure;

	MStatus returnStatus;
	/* Get time */
	MDataHandle timeData = datablock.inputValue( aTime, &returnStatus ); 
	MCHECKERROR(returnStatus, "Error getting time data handle\n")
	MTime time = timeData.asTime();
	//!< 30 frames per second
	int	  frame = (int)time.as( MTime::kNTSCFrame ) - 1;//Noted: The first frame in MAYA is 1;

	if(m_pDevice)
	{
		std::shared_ptr<NuiCompositeFrame> pFrame = m_pDevice->popFrame();
		if(pFrame)
		{
			pFrame->m_depthFrame.SetMinDepth(getShortValue(aMinDepth));
			pFrame->m_depthFrame.SetMaxDepth(getShortValue(aMaxDepth));

			if(m_pSLAM /*&& m_pSLAM->m_tracker.isThreadOn()*/)
			{
				std::shared_ptr<NuiVisualFrame> pVisualFrame = std::make_shared<NuiVisualFrame>();
				pVisualFrame->acquireFromCompositeFrame(pFrame.get());
				m_pSLAM->m_tracker.pushbackFrame(pVisualFrame);
				pVisualFrame.reset();
			}
			m_pCache->pushbackFrame(pFrame);
			pFrame.reset();
		}
	}

	std::shared_ptr<NuiCompositeFrame> pCurrentFrame = m_pCache->getLatestFrame();
		
	if ( plug == aOutputMappable )
	{
		std::shared_ptr<NuiCLMappableData> clData(nullptr);
		MDataHandle outHandle = datablock.outputValue( aOutputMappable );
		NuiMayaMappableData* clmData = static_cast<NuiMayaMappableData*>(outHandle.asPluginData());
		if(!clmData)
		{
			// Create some user defined geometry data and access the
			// geometry so we can set it
			//
			MFnPluginData fnDataCreator;
			MTypeId tmpid( NuiMayaMappableData::id );

			fnDataCreator.create( tmpid, &returnStatus );
			MCHECKERROR( returnStatus, "compute : error creating mappableData")

			clmData = (NuiMayaMappableData*)fnDataCreator.data( &returnStatus );
			MCHECKERROR( returnStatus, "compute : error gettin at proxy mappableData object")

			clData = std::shared_ptr<NuiCLMappableData>(new NuiCLMappableData());
			clmData->setData(clData);

			returnStatus = outHandle.set( clmData );
			MCHECKERROR( returnStatus, "compute : error gettin at proxy mappableData object")
		}
MStatus NuiMayaDeviceGrabber::initialize()
//
//	Description:
//		This method is called to create and initialize all of the attributes
//      and attribute dependencies for this node type.  This is only called 
//		once when the node type is registered with Maya.
//
//	Return Values:
//		MS::kSuccess
//		MS::kFailure
//
{
	// This sample creates a single input float attribute and a single
	// output float attribute.
	//
	MFnNumericAttribute nAttr;
	MFnTypedAttribute	typedAttr;
	MFnUnitAttribute	unitAttr;
	MFnEnumAttribute	enumAttr;
	MStatus				stat;

	aTime = unitAttr.create( "time", "tm",
		MFnUnitAttribute::kTime,
		0.0, &stat );
	stat = addAttribute( aTime );
	if (!stat) { stat.perror("addAttribute time"); return stat;}

	aUseCache = nAttr.create( "useCache", "uc", MFnNumericData::kBoolean, false );
	// Attribute will be written to files when this type of node is stored
	nAttr.setStorable(true);
	// Attribute is keyable and will show up in the channel box
	stat = addAttribute( aUseCache );
	if (!stat) { stat.perror("addAttribute"); return stat;}

	aDeviceOn = nAttr.create( "deviceOn", "do", MFnNumericData::kBoolean, false );
	// Attribute will be written to files when this type of node is stored
	nAttr.setStorable(true);
	// Attribute is keyable and will show up in the channel box
	stat = addAttribute( aDeviceOn );
	if (!stat) { stat.perror("addAttribute"); return stat;}

	aDeviceMode = enumAttr.create( "deviceMode", "dm", NuiRGBDDeviceController::EDeviceMode_VertexColorCamera, &stat );
	if (!stat) { stat.perror("create DeviceMode attribute"); return stat;}
	stat = enumAttr.addField( "Depth,Color", NuiRGBDDeviceController::EDeviceMode_DepthColor );
	if (!stat) { stat.perror("add enum type DepthColor"); return stat;}
	stat = enumAttr.addField( "Depth,Color,Player", NuiRGBDDeviceController::EDeviceMode_VertexColorCamera );
	if (!stat) { stat.perror("add enum type DepthColorPlayer"); return stat;}
	stat = enumAttr.addField( "Depth,Color,Skeleton", NuiRGBDDeviceController::EDeviceMode_VertexColorSkeleton );
	if (!stat) { stat.perror("add enum type DepthColorSkeleton"); return stat;}
	stat = enumAttr.addField( "Depth,Color,Skeleton,Face", NuiRGBDDeviceController::EDeviceMode_VertexColorSkeletonFace );
	if (!stat) { stat.perror("add enum type DepthColorSkeletonFace"); return stat;}
	stat = enumAttr.addField( "Depth,Color,Skeleton,Gesture", NuiRGBDDeviceController::EDeviceMode_VertexColorSkeletonGesture );
	if (!stat) { stat.perror("add enum type DepthColorSkeletonGesture"); return stat;}
	stat = enumAttr.addField( "Color", NuiRGBDDeviceController::EDeviceMode_Color );
	if (!stat) { stat.perror("add enum type Color"); return stat;}
	stat = enumAttr.addField( "Depth", NuiRGBDDeviceController::EDeviceMode_Vertex );
	if (!stat) { stat.perror("add enum type Depth"); return stat;}
	stat = enumAttr.addField( "Skeleton", NuiRGBDDeviceController::EDeviceMode_Skeleton );
	if (!stat) { stat.perror("add enum type Skeleton"); return stat;}
	stat = enumAttr.addField( "Fusion", NuiRGBDDeviceController::EDeviceMode_Fusion );
	if (!stat) { stat.perror("add enum type fusion"); return stat;}
	CHECK_MSTATUS( enumAttr.setHidden( false ) );
	CHECK_MSTATUS( enumAttr.setKeyable( false ) );
	stat = addAttribute( aDeviceMode );
	if (!stat) { stat.perror("addAttribute"); return stat;}

	aNearMode = nAttr.create( "nearMode", "ne", MFnNumericData::kBoolean, false );
	// Attribute will be written to files when this type of node is stored
	nAttr.setStorable(true);
	// Attribute is keyable and will show up in the channel box
	stat = addAttribute( aNearMode );
	if (!stat) { stat.perror("addAttribute"); return stat;}

	aElevationAngle = nAttr.create( "elevationAngle", "ea", MFnNumericData::kInt, 0 );
	// Attribute will be written to files when this type of node is stored
	nAttr.setStorable(true);
	nAttr.setKeyable(true);
	nAttr.setMin(-27);
	nAttr.setMax(27);
	// Attribute is keyable and will show up in the channel box
	stat = addAttribute( aElevationAngle );
	if (!stat) { stat.perror("addAttribute"); return stat;}

	aPreviewerOn = nAttr.create( "previewerOn", "po", MFnNumericData::kBoolean, false );
	// Attribute will be written to files when this type of node is stored
	nAttr.setStorable(true);
	// Attribute is keyable and will show up in the channel box
	stat = addAttribute( aPreviewerOn );
	if (!stat) { stat.perror("addAttribute"); return stat;}

	aKinFuOn = nAttr.create( "fusionOn", "fo", MFnNumericData::kBoolean, false );
	// Attribute will be written to files when this type of node is stored
	nAttr.setStorable(true);
	// Attribute is keyable and will show up in the channel box
	stat = addAttribute( aKinFuOn );
	if (!stat) { stat.perror("addAttribute"); return stat;}

	aVolumeVoxelSize = nAttr.create( "volumeVoxelSize", "vvs", MFnNumericData::kFloat, 0.01f );
	// Attribute will be written to files when this type of node is stored
	nAttr.setStorable(true);
	nAttr.setKeyable(true);
	nAttr.setMin(0.005f);
	nAttr.setMax(0.02f);
	// Attribute is keyable and will show up in the channel box
	stat = addAttribute( aVolumeVoxelSize );
	if (!stat) { stat.perror("addAttribute"); return stat;}

	aShowInvalid = nAttr.create("showInvalid", "siv", MFnNumericData::kBoolean, false, &stat);
	MCHECKERROR( stat, "create showInvalid attribute" )
	nAttr.setKeyable(true);
	ADD_ATTRIBUTE( aShowInvalid );

	aShowOnlyBody = nAttr.create("showOnlyBody", "sc", MFnNumericData::kBoolean, false, &stat);
	MCHECKERROR( stat, "create showOnlyBody attribute" )
	nAttr.setKeyable(true);
	ADD_ATTRIBUTE( aShowOnlyBody );

	aShowMesh = nAttr.create("showMesh", "sm", MFnNumericData::kBoolean, false, &stat);
	MCHECKERROR( stat, "create showMesh attribute" )
	nAttr.setKeyable(true);
	ADD_ATTRIBUTE( aShowMesh );

	aMinDepth = nAttr.create( "nearPlane", "np", MFnNumericData::kShort, 400 );
	// Attribute will be written to files when this type of node is stored
	nAttr.setStorable(true);
	nAttr.setKeyable(true);
	nAttr.setMin(400);
	nAttr.setMax(4500);
	// Attribute is keyable and will show up in the channel box
	stat = addAttribute( aMinDepth );
	if (!stat) { stat.perror("addAttribute"); return stat;}

	aMaxDepth = nAttr.create( "farPlane", "fp", MFnNumericData::kShort, 4200 );
	// Attribute will be written to files when this type of node is stored
	nAttr.setStorable(true);
	nAttr.setKeyable(true);
	nAttr.setMin(400);
	nAttr.setMax(4500);
	// Attribute is keyable and will show up in the channel box
	stat = addAttribute( aMaxDepth );
	if (!stat) { stat.perror("addAttribute"); return stat;}


	// ----------------------- OUTPUTS -------------------------
	aOutputMappable = typedAttr.create( "outputPointCloud", "opc",
		NuiMayaMappableData::id,
		MObject::kNullObj, &stat );
	if (!stat) { stat.perror("create outputPointCloud attribute"); return stat;}
	typedAttr.setWritable( false );
	typedAttr.setStorable(false);
	stat = addAttribute( aOutputMappable );
	if (!stat) { stat.perror("addAttribute"); return stat;}

	aOutputSkeleton = typedAttr.create( "outputSkeleton", "osk",
		NuiMayaSkeletonData::id,
		MObject::kNullObj, &stat );
	if (!stat) { stat.perror("create outputSkeleton attribute"); return stat;}
	typedAttr.setWritable( false );
	typedAttr.setStorable(false);
	stat = addAttribute( aOutputSkeleton );
	if (!stat) { stat.perror("addAttribute"); return stat;}

	aOutputMesh = typedAttr.create( "outputMesh", "om",
		MFnData::kMesh,
		MObject::kNullObj, &stat );
	MCHECKERROR( stat, "create outputSurface attribute" )
		typedAttr.setWritable( false );
	ADD_ATTRIBUTE( aOutputMesh );

	aOutputGesture = typedAttr.create( "outputGesture", "ogs",
		NuiMayaGestureData::id,
		MObject::kNullObj, &stat );
	if (!stat) { stat.perror("create outputGesture attribute"); return stat;}
	typedAttr.setWritable( false );
	typedAttr.setStorable(false);
	stat = addAttribute( aOutputGesture );
	if (!stat) { stat.perror("addAttribute"); return stat;}

	aOutputFacialModel = typedAttr.create( "outputFacialModel", "ofm",
		NuiMayaFacialModelData::id,
		MObject::kNullObj, &stat );
	if (!stat) { stat.perror("create outputFacialModel attribute"); return stat;}
	typedAttr.setWritable( false );
	stat = addAttribute( aOutputFacialModel );
	if (!stat) { stat.perror("addAttribute"); return stat;}

	aFaceRotateX = nAttr.create( "faceRotateX", "frX", MFnNumericData::kDouble, 0.0, &stat );
	if (!stat) { stat.perror("create face rotateX attribute"); return stat;}
	nAttr.setReadable( true );
	nAttr.setWritable( false );
	nAttr.setStorable(true);
	aFaceRotateY = nAttr.create( "faceRotateY", "frY", MFnNumericData::kDouble, 0.0, &stat );
	if (!stat) { stat.perror("create face rotateY attribute"); return stat;}
	nAttr.setReadable( true );
	nAttr.setWritable( false );
	nAttr.setStorable(true);
	aFaceRotateZ = nAttr.create( "faceRotateZ", "frZ", MFnNumericData::kDouble, 0.0, &stat );
	if (!stat) { stat.perror("create rotateZ attribute"); return stat;}
	nAttr.setReadable( true );
	nAttr.setWritable( false );
	nAttr.setStorable(true);
	aFaceRotate = nAttr.create( "faceRotate", "fr", aFaceRotateX, aFaceRotateY, aFaceRotateZ, &stat );
	if (!stat) { stat.perror("create face rotate attribute"); return stat;}
	nAttr.setDefault(0.0f, 0.0f, 0.0f);
	nAttr.setReadable( true );
	nAttr.setWritable( false );
	nAttr.setStorable(true);
	stat = addAttribute( aFaceRotate );
	if (!stat) { stat.perror("addAttribute"); return stat;}

	aCameraRotateX = nAttr.create( "cameraRotateX", "crX", MFnNumericData::kDouble, 0.0, &stat );
	if (!stat) { stat.perror("create cameraRotateX attribute"); return stat;}
	nAttr.setReadable( true );
	nAttr.setWritable( false );
	nAttr.setStorable(true);
	aCameraRotateY = nAttr.create( "cameraRotateY", "crY", MFnNumericData::kDouble, 0.0, &stat );
	if (!stat) { stat.perror("create rotateY attribute"); return stat;}
	nAttr.setReadable( true );
	nAttr.setWritable( false );
	nAttr.setStorable(true);
	aCameraRotateZ = nAttr.create( "cameraRotateZ", "crZ", MFnNumericData::kDouble, 0.0, &stat );
	if (!stat) { stat.perror("create rotateZ attribute"); return stat;}
	nAttr.setReadable( true );
	nAttr.setWritable( false );
	nAttr.setStorable(true);
	aCameraRotate = nAttr.create( "cameraRotate", "cr", aCameraRotateX, aCameraRotateY, aCameraRotateZ, &stat );
	if (!stat) { stat.perror("create cameraRotate attribute"); return stat;}
	nAttr.setDefault(0.0f, 0.0f, 0.0f);
	nAttr.setReadable( true );
	nAttr.setWritable( false );
	nAttr.setStorable(true);
	stat = addAttribute( aCameraRotate );
	if (!stat) { stat.perror("addAttribute"); return stat;}

	aCameraTranslateX = nAttr.create( "cameraTranslateX", "ctX", MFnNumericData::kDouble, 0.0, &stat );
	if (!stat) { stat.perror("create cameraTranslateX attribute"); return stat;}
	nAttr.setReadable( true );
	nAttr.setWritable( false );
	nAttr.setStorable(true);
	aCameraTranslateY = nAttr.create( "cameraTranslateY", "ctY", MFnNumericData::kDouble, 0.0, &stat );
	if (!stat) { stat.perror("create cameraTranslateY attribute"); return stat;}
	nAttr.setReadable( true );
	nAttr.setWritable( false );
	nAttr.setStorable(true);
	aCameraTranslateZ = nAttr.create( "cameraTranslateZ", "ctZ", MFnNumericData::kDouble, 0.0, &stat );
	if (!stat) { stat.perror("create cameraTranslateZ attribute"); return stat;}
	nAttr.setReadable( true );
	nAttr.setWritable( false );
	nAttr.setStorable(true);
	aCameraTranslate = nAttr.create( "cameraTranslate", "ct", aCameraTranslateX, aCameraTranslateY, aCameraTranslateZ, &stat );
	if (!stat) { stat.perror("create cameraTranslate attribute"); return stat;}
	nAttr.setDefault(0.0f, 0.0f, 0.0f);
	nAttr.setReadable( true );
	nAttr.setWritable( false );
	nAttr.setStorable(true);
	stat = addAttribute( aCameraTranslate );
	if (!stat) { stat.perror("addAttribute"); return stat;}

	// Set up a dependency between the input and the output.  This will cause
	// the output to be marked dirty when the input changes.  The output will
	// then be recomputed the next time the value of the output is requested.
	//
	stat = attributeAffects( aTime, aOutputMappable );
	if (!stat) { stat.perror("attributeAffects"); return stat;}
	stat = attributeAffects( aTime, aOutputSkeleton );
	if (!stat) { stat.perror("attributeAffects"); return stat;}
	stat = attributeAffects( aTime, aOutputFacialModel );
	if (!stat) { stat.perror("attributeAffects"); return stat;}
	stat = attributeAffects( aTime, aFaceRotateX );
	if (!stat) { stat.perror("attributeAffects"); return stat;}
	stat = attributeAffects( aTime, aFaceRotateY );
	if (!stat) { stat.perror("attributeAffects"); return stat;}
	stat = attributeAffects( aTime, aFaceRotateZ );
	if (!stat) { stat.perror("attributeAffects"); return stat;}
	stat = attributeAffects( aTime, aFaceRotate );
	if (!stat) { stat.perror("attributeAffects"); return stat;}
	stat = attributeAffects( aTime, aCameraRotateX );
	if (!stat) { stat.perror("attributeAffects"); return stat;}
	stat = attributeAffects( aTime, aCameraRotateY );
	if (!stat) { stat.perror("attributeAffects"); return stat;}
	stat = attributeAffects( aTime, aCameraRotateZ );
	if (!stat) { stat.perror("attributeAffects"); return stat;}
	stat = attributeAffects( aTime, aCameraRotate );
	if (!stat) { stat.perror("attributeAffects"); return stat;}
	stat = attributeAffects( aTime, aCameraTranslateX );
	if (!stat) { stat.perror("attributeAffects"); return stat;}
	stat = attributeAffects( aTime, aCameraTranslateY );
	if (!stat) { stat.perror("attributeAffects"); return stat;}
	stat = attributeAffects( aTime, aCameraTranslateZ );
	if (!stat) { stat.perror("attributeAffects"); return stat;}
	stat = attributeAffects( aTime, aCameraTranslate );
	if (!stat) { stat.perror("attributeAffects"); return stat;}

	return MS::kSuccess;
}