View Full Version : API: How to store pre-computed data on deforer node
06 June 2007, 05:25 PM
I'm writing a custom deformer and as part of the compute method I need access to some custom data that should (ideally) be initialized at the time of the creation of the node itself (perhaps in the creation method?). My problem is that I don't know how to go about creating this data and/or accessing it inside compute().
Basically, I want to pre-compute all the edge lengths of the polygon mesh and have access to a float array of intial un-deformed edge-lengths during the compute method. That way I can compare the initial edge lengths to the current edge lengths and use this in my deformation algorithm.
I was thinking I could create an intermediate shape node and connect it's outputGeom to a custom attribute on the deformer node. Then I could access the edge data through the datablock inside compute(). I'm sure this would work, but this would mean that I would have to re-compute all the edge lengths during EVERY call to compute!
I also looked into using MPxData but this seems more suited to creating custom data types to pass between nodes in the DG. I just simply want some data to be initialized with the creation of the node and then stay put inside the node until the compute/deform method calls upon it to read/edit it.
Surely, people have saved or pre-computed custom data into their nodes. I can't see why this is so hard...
Any ideas would be greatly appreciated. Thanks!
06 June 2007, 05:39 PM
How about storing the data array as a member of the derived deformer class? You'd have to make sure it's always "up to date", but I think that'd be the easiest and the fastest way of accessing it for calculation purposes.
06 June 2007, 05:48 PM
Connecting an extra initial (or base) shape to the deformer (which is the undeformed non-animated shape) is definitely the way to go. You can then calculate all the data you're interested in from that and store it internally. There's no way to calculate that on "initialize", since when the deformer gets created, it's not connected to its inputs yet.
To avoid recomputing that every single time, you can detect when the "base" shape gets dirty (and only recompute when the base shape changes for some reason, which would probably be never in your case) by using setDependentsDirty(). When that function gets called for the initialShape attribute, you can set an internal boolean "initialShapeIsDirty". Then in your compute method, only recompute your data if the shape is dirty. Take a look at the affectsNode example plugin in the devkit.
06 June 2007, 07:19 PM
Ack - sorry, got my calls confused; what you're interested in is setInternalValue(). This is specifically mean't for you to update internal data when an input changes. Check out the apiMeshShape or the quadricShape in the devKit for examples....
06 June 2007, 10:28 PM
JackSMillenium - Thank you very much. Using the 'isDirty' flag should work very well as a reliable way to determine when, if at all, I will need to recompute the internal data.
On a similar note, I have a more general programming question. I need to create an array of custom objects (for vertex data). This array has a size coorsesponding to the number of vertices in the mesh (which I don't know until run-time).
So I need to dynamically create an array of data structures. Can anyone recommend the best way to go? I was going to create a pointer to the array in my base deformer class and then use the 'new' operator to create a new array 'on-the-fly' of the particular size needed. Alternatively, I was thinking of use the vector class from the std library because I heard it can dynamically changes size quite easily with minimal overhead.
Just curious if any of you have experience with this sort of thing. I'm coming from a more structured programming background and have a lot to learn about object-oriented programming and all it's finer caveats.
06 June 2007, 09:29 AM
As you've practically ignored my previous post I didn't really feel like replying, but here you go:
new  and delete  would work fine for simple dynamic allocations. You just have to not forget deleting that pointer when you don't need the memory anymore (the destructor should be the right place for it).
Resizing or replacing such a dynamic array would require a bit more effort. You'd have to free the previous memory, and recreate the array of the new size. The problem with these is that the slightest error in this low level code (like deleting the pointer twice, accessing deallocated pointer, etc) will immediately crash your program.
Thus in C++, it's considered a better style to use STL's vector container. Performance wise, vector class just encapsulates new/delete kind of functionality, and handles dynamic resizing for you. When your array of size n is filled, and you want to insert a new element to it, vector will allocate a new array of size 2*n (1.3*n in some implementations), copying your n data elements to the new array. It also handles deleting the pointer to your data when the vector object is destroyed.
You could save some unnecessary reallocations of the vector if you know the array size before hand. By using the reserve(size_t size) method you force the vector object to have enough space to hold size elements. The future insertions to this array will be very fast, given you won't insert more than size elements.
Another important performance note about vector container, and STL containers in general: the "insert" method takes a "by-copy" argument. That means that when you call insert with an object argument, that object first gets copied and then parsed into the procedure.
This makes inserting big data structures rather inefficient. Instead it is preferred to hold a vector of pointers to big data structures.
So as you may see both ways have their pros and cons. For simple dynamic allocation I'd probably go with new/delete approach, as it's very straight forward. If you need more safety or functionality like insert/delete, auto grow/shrink, I'd go with vector container.
Hope that helps,
06 June 2007, 05:54 PM
Henry Korol -Thank you very much for the help! I didn't mean to ignore your first post, just that I wasn't sure exactly how to go about storing member data in a dynamic way.
I think for my purposes, using the new/delete operator's will suffice. Simply because I don't anticipate needing any re-sizing functionality. Just dynamic allocation of a memory block at run-time. If it needs updating, I can call the delete operator and get more/less memory by calling 'new' again. Then I will do a full re-compute. If pre-computing was a looong process (which I don't think it will be) then I would go with the vector class so that I could grow/shrink the array as needed. I also made sure to delete the pointer in the MPxDeformer sub-class' destructor (good to know I was on the right path here).
So far it's working very well and it's good to know that the std vector class is there if I need it. I wasn't even sure if it would have worked, so thank you for clarifying that.
Big thanks to both you guys for all your help. I hope I can release this deformer as open-source at some point in the near future.
06 June 2007, 02:13 AM
yeah... pen and paper mabey ? ;P.. I saw u posting jibberish under my account name.... lol.. just kidding..
peace out monkey.
06 June 2007, 02:13 AM
This thread has been automatically closed as it remained inactive for 12 months. If you wish to continue the discussion, please create a new thread in the appropriate forum.