Hi all,
I've been working on a dependency graph (like the one found in Autodesk Maya). Every node in the graph derives from a `DependencyNode` class, a node will have a set of input and output plugs, where the value of the output plugs is calculated in a `compute` function which is overridden from the `DependencyNode` class. You can connect output plugs to input plugs of other nodes, thus by chaining together multiple nodes, can create complex behaviors.
Simplified DependencyNode super class header:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
|
#include <unordered_map>
#include <string>
#include "Plug.h"
class DependencyNode
{
public:
DependencyNode(std::string name);
virtual ~DependencyNode();
virtual void initialize() = 0;
virtual void compute()=0;
std::string getName() { return this->mName; }
void setName(std::string name) { this->mName = name; }
void addPlug(Plug plug) { this->mPlugs.insert(std::pair<std::string, Plug>(plug->getName(), plug)); }
Plug& getPlug(std::string name) { return this->mPlugs.find(name)->second; }
private:
std::string mName;
std::unordered_map<std::string, Plug> mPlugs;
};
|
Now for example if you wanted to create a multiply node, you would subclass `DependencyNode`, add three plugs to it as member variables (two inputs, one output) and during the compute function would set the output to be the value of the two inputs multiplied together.
My current issue is each plug can be one of many types, it could store a float, double, a 4x4 matrix or even some kind of OpenGL type as an example. You can also only connect outputs to inputs that both have the same type.
Finally my question: Each node needs to store the data of all its plugs. I know Maya uses some kind of contiguous allocated memory block to do so for its implementation, and I was thinking of allocating a block of memory equivalent to the size of all the plugs value types added together. i.e if there were two floats and a double then the allocated memory size would be `sizeof(float) * 2 + size(double)`. Then each plug would store an offset on where to find its particular data, and what type of data it is. However I quickly ran into problems. Say I allocate memory with `malloc` and receive a void* in return. I can't perform pointer arithmetic on a void* as it's not an object type, nor can I cast the void* to a specific type as the data block could contain any number of types.(Unless I casted to char*, did the arithmetic, then casted to the appropriate type) but this feels really hacky. The other important factor here is speed, as the graph would be evaluated in real time, many many timers per second, with most of the time being taken up in user-defined compute functions, so the back-end of the graph needs to be as fast as possible.
Any ideas on how I could implement such a thing? Thanks!