How can I cache data for a custom locator?

How can I cache data for a custom locator?

jmreinhart
Advisor Advisor
897 Views
6 Replies
Message 1 of 7

How can I cache data for a custom locator?

jmreinhart
Advisor
Advisor

I am working on a custom locator that has "inputMesh" and "faceIDs" (an intArray) attributes. I am using those inputs to draw the faces with the given face IDs. I have this working but I want to speed it up by caching the vertices of the triangles that I need to draw, so that I don't need to re-evaluate that data in "prepareForDraw". At the moment I'm trying to use the setDependentsDirty method to flag which plugs have been edited, and then store the data we get from the plugs in "prepareForDraw" the first time we evaluate or any time the faceIDs attribute is changed. But I cannot access the data I stored from inside the "prepareForDraw" method. I tried turning the dagPath into an mObject and casting it as my MpxLocator class, but that didn't work.

 

Is there an alternative method I can use?

0 Likes
Accepted solutions (1)
898 Views
6 Replies
Replies (6)
Message 2 of 7

jmreinhart
Advisor
Advisor

So I got the recasting working (I think). The problem is, when I try to get the inputMesh_dirty or faces_dirty value by writing something like this:

MObject obj = objPath.node(&status);
meshLocator* newDerived = (meshLocator*)&obj;
newDerived->get_inputMesh_dirty();

I always get 204 as the result which is unexpected because "get_inputMesh_dirty" returns a boolean. 

 

I think I'm misunderstanding something about this C++ syntax.

I've attached the full code to this page, any help would be greatly appreciated.

0 Likes
Message 3 of 7

jmreinhart
Advisor
Advisor

So I've done some additional troubleshooting and it turns out that setDependentsDirty was not being called at all. I don't know if fixing that will fix the issue, but I need to find out why that is happening first. 

 

Why isn't  setDependentsDirty  being called?

0 Likes
Message 4 of 7

jmreinhart
Advisor
Advisor

So it seems like setDependentsDirty was not being called because I was missing a const, though I made some other syntax changes too so that may not have been the only issue.

 

class meshLocator : public MPxLocatorNode
{
public:
	//add attributes
	static MObject faces;
	static MObject inputMesh;
	static MObject outputDummy;

public:
	void set_faces_dirty(bool value){faces_dirty = value;}
	bool get_faces_dirty(){return faces_dirty;}

	void set_inputMesh_dirty(bool value) { inputMesh_dirty = value; }
	bool get_inputMesh_dirty() { return inputMesh_dirty; }

private:
	//flags to allow us to cache data
	bool inputMesh_dirty = false;
	bool faces_dirty = false;
};

MUserData* testDrawOverride::prepareForDraw(
	const MDagPath& objPath,
	const MDagPath& cameraPath,
	const MFrameContext& frameContext,
	MUserData* oldData)
{
	//get the MObject
	MObject obj = objPath.node(&status);
	meshLocator* newDerived = (meshLocator*)&obj;
	MFnDependencyNode mFn(obj);

	//============================
	//get the inputMesh data if faces or inputMesh are dirty
	//============================
	bool inputMesh_dirty = newDerived->get_inputMesh_dirty();
	MGlobal::displayInfo(MString("inputMesh is dirty:") + (inputMesh_dirty == 1));
	MGlobal::displayInfo(MString("inputMesh is clean:") + (inputMesh_dirty == 0));
}

I think I've pinned down what the issue is. When I try to cast the mObject as a meshLocator, I won't have access to the data I stored on that node because casting a child class as a parent won't work like that. 

 

I suppose that I could create output attributes on the meshLocator node to hold the data that I want to pass into here, but getting that data via plugs seems like it would be unnecessarily slow. 

 

Is there a better method or is that dummy output method the "correct" way to do this?

0 Likes
Message 5 of 7

jmreinhart
Advisor
Advisor

So I tried out the method of "caching data" on the actual spaceLocator node itself. It's computing and storing just fine but I've run into an issue when trying to use that data to draw. I get the data in the prepareToDraw method and store it in the MUserData derived class, but when I try to get it out of the data it crashes. The crash only happens when I try to get the MPointArray I have in my MUserData derived class. While trying to find out what the issue I occasionally got an MPointArray with a crazy length like 90,000 or something, but most of the time it had no length or it crashed. I've attached my .cpp in case that helps. I'll keep working on this issue when I can but I've just about run out of ideas. Any help would be greatly appreciated.

0 Likes
Message 6 of 7

jmreinhart
Advisor
Advisor

So after some troubleshooting I found out that I can pass an MPoint into the MUserData and pull it out in the addUIDrawables method. But doing the same with an MPointArray will cause a crash. I tested with a simple intArray and had no issues. And I tested with an empty MPointArray and had no issues. I'm really at a loss as to what could be happening. Any ideas?

0 Likes
Message 7 of 7

jmreinhart
Advisor
Advisor
Accepted solution

So after a lot of testing I suspect that my issue is a result of an API bug because I tested converting the MPointArray to an MVectorArray and back again in the addUIDrawables method, and that works fine with no issues. So something about retrieving the MPointArray from the MUserData seems broken. I'm using Maya 2018 and Visual Studio 2015 for anyone who comes across this post in the future.