Changing frameRate attribute of MPxThreadedDeviceNode

Changing frameRate attribute of MPxThreadedDeviceNode

Anonymous
Not applicable
480 Views
1 Reply
Message 1 of 2

Changing frameRate attribute of MPxThreadedDeviceNode

Anonymous
Not applicable

I've created a plugin where serial data is read, parsed and a cube's rotation is updated based on that data. The serial data comes in at 120hz and includes comma spliced rotation values. Those values are changed via a joystick on the serial device. 

 

To do this I use MPxThreadedDeviceNodeto attach a cubes rotation attributes to an attribute on my threaded node. This threaded node also starts a separate thread which opens a Serial port, parse the data, and stores it in a static class. In the threadHandler of the threaded node, it gets the rotation values from the static class and updates the attributes.

 

What I'm noticing is there is about a second delay from when I push the joystick, to when its actually updated in Maya. I believe this has to do with the way the threaded node is updating the cube, as watching the raw serial data, it doesn't look like theirs that big of a delay.

 

I see that there's an attribute on MPxThreadedDeviceNode thats "static MObject frameRate". This attribute has the description: 

  • The live and frameRate attributes are included in this class. Changes to these attributes will cause the thread to be shutdown and restarted so that the new settings can be in effect.

I'm thinking I need to increase the frameRate, so that the changes happen more instantaneously. I'm just not sure how to set that attribute. It says its a double, but the type is actually MObject. How can I set the frameRate to something like 120.  Maybe I'm going at this wrong and its a setting I change directly in maya?

 

Here is my MPxThreadedNode class. I've omitted standard functions like the constructor and deconstructor. I've also not shown my Serial class (RiverSerialCommunication) as it basically is just a class with some static variables.

 

 

void RiverControllerNode::postConstructor() {
	MObjectArray attrArray;
	attrArray.append(RiverControllerNode::outputRotate);
	setRefreshOutputAttributes(attrArray);

	// Create 3 axis rotational data
	createMemoryPools(24, 3, sizeof(double));

	MThreadAsync::createTask(RiverSerialCommunication::Start, this, NULL, NULL);
}

void RiverControllerNode::threadHandler() 
{
	MStatus status;
	setDone(false);

	// Loop until thread is killed
	while (!isDone())
	{
		// Live allows for thread pausing
		if (!isLive())
			continue;

		
		// Get buffer to write to
		MCharBuffer buffer;
		status = acquireDataStorage(buffer);
		if (!status)
			continue;
		
		// Data Operations
		beginThreadLoop();
		{
			// Convert buffer to x,y,z rotation data
			double* doubleData = reinterpret_cast<double*>(buffer.ptr());


			// Get serial data
			doubleData[0] = RiverSerialCommunication::GetPan();
			doubleData[1] = RiverSerialCommunication::GetTilt();

			// Push the data for the main thread to compute
			pushThreadData(buffer);
		}

		// Perform the throttling based on the frame rate attribute and additionally cause the output attribute to be marked dirty causing compute() to run
		endThreadLoop();
	}
}

void RiverControllerNode::threadShutdownHandler()
{
	// Break the loop in threadHandler
	setDone(true);
}


/*
* @brief Runs on the main thread after the thread loop has run and marked the data dirty
*/
MStatus	RiverControllerNode::compute(const MPlug& plug, MDataBlock& data)
{
	MStatus status;

	// Access the data and update the output attribute
	MCharBuffer buffer;
	if (popThreadData(buffer))
	{
		// Relative data coming in
		double* doubleData = reinterpret_cast<double*>(buffer.ptr());

		MDataHandle outputTranslateHandle = data.outputValue(outputRotate, &status);
		double3& outputRotate = outputTranslateHandle.asDouble3();

		outputRotate[0] = doubleData[0];
		outputRotate[1] = doubleData[1];
		outputRotate[2] = 0;

		data.setClean(plug);

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


MStatus RiverControllerNode::initialize()
{
	MStatus status;
	MFnNumericAttribute numAttr;

	outputRotateX = numAttr.create("outputRotateX", "orx", MFnNumericData::kDouble, 0.0, &status);
	outputRotateY = numAttr.create("outputRotateY", "ory", MFnNumericData::kDouble, 0.0, &status);
	outputRotateZ = numAttr.create("outputRotateZ", "orz", MFnNumericData::kDouble, 0.0, &status);
	outputRotate = numAttr.create("outputRotate", "or", outputRotateX, outputRotateY, outputRotateZ, &status);

	numAttr.setKeyable(true);
	numAttr.setStorable(true);
	numAttr.setHidden(false);
	numAttr.setDefault(true);

	addAttribute(outputRotate);

	attributeAffects(live, outputRotate);
	attributeAffects(frameRate, outputRotate);

	return MS::kSuccess;
}

 

TL;DR: How can I change the frameRate attribute of MPxThreadedDeviceNode.

 

 

0 Likes
481 Views
1 Reply
Reply (1)
Message 2 of 2

cheng_xi_li
Autodesk Support
Autodesk Support

Hi,

 

You should be able to update it with MPlug like other attributes.

 

e.g. 

MPlug plugFrameRate(thisMObject(), frameRate);
plugFrameRate.setDouble(desiredFrameRate);

If you wanted to have an initial value, you could set it in MPxNode::postConstructor().

 

Hope it helps.

 

Yours,

Li

0 Likes