Node-Based Coding ...
Atually you can achieve this without the pull approach if you think in terms of dirty attributes and not dirty nodes. In your example you had one set of attributes holding image data, and another holding a channel mask. So your dependency flow actually looks like this if you think in terms of attributes
GUI.image
|
Reorder.image
|
Blur.image
|
FileIn.image
|
FileIn.mask
|
Blur.mask
|
Reorder.mask
|
GUI.mask
Notice in the above where FileIn.image requires data from FileIn.mask. All the other connections are external node-to-node connections, but the FileIn.image and FileIn.mask are an internal dependency. The FileIn node probably requires inputs of “mask” and “filename”, and has an output of “image”. The “image” output is dependent on clean values from mask and filename, so these two internal dependencies are created by default when the FileIn node is created.
You can accomplish the same as a Push paradigm by simply propogating dirty flags, and then letting the pull approach actually get the data. For example, let’s say that the file on disk changes, thus invalidating the FileIn node (the FileIn node would probably have to be set up in some timed polling event so it could check if the files on disk changed). The FileIn node sets its filename attribute to dirty. Since there is a dependency connection from filename to image, the image attribute is set to dirty. When the FileIn.image attribute is dirtied, it passes the dirty state along its connections, so Blur.image is set to dirty. This in turn sets Reorder.image to dirty, which sets GUI.image to dirty.
Now the next time the GUI is updated, it sees that it needs to recalculate the image so it calls on Reorder.image to give it data, which asks Blur for its image node, etc on down the line. Once it gets to FileIn, the cached value for mask is used because that attribute wasn’t dirtied this time around, so it should still be valid.
And yes, Hugh. I do happen to be a Maya user…
And no I’m not copying their MEL syntax… completely… hehehe…
Cheers,
Michael Duffy
Just found this and thought it might be useful http://www.boost.org/libs/graph/doc/index.html
Has anyone used this? It looks a lot easier than rollign your own. (you still have to deal with your own GUI callbacks though).
Simon
Cheers Simon, will look into that when I get some time! Busy, busy, busy - too many project finishing!! 
Ta
Dan
I’ve thought about this for awhile sometime ago, and I thought it’d be fun and easy to implement. I’m just wondering, are you guys all doing this for fun in your own projects?
Hi orgee
Why I’m looking into this is for a crowd sim project I’m working on at the moment, and I’m thinking of designing a node network so that users can code the ‘brains’ of the agents of the simulation.
I’d be interested to hear your views/ideas on node-based programming and designing a similar system to material networks (ie. HyperShade in Maya, Houdini’s procedural coding interace, etc) …
Hugh & MDuffy has already outlined a good way of implementing a ‘HyperShade-like’ system. ![]()
I’ve thought about crowd sims, but really written them down, so here goes:
For each agent, you have 1 Brain Node, which is evaluates all the ‘thinking’-nodes connected to it which determine what action to do next. That is the basic system.
An action is an index of a certain move which the agent already knows. In the case of a crowd sim for an animation, actions would be a list of clips the character has, such as walking, falling, jumping and so forth. To go even more advanced, you can make the action a certain character movement control, which instead of having an index for running, you’ll have controls for parts of the agent such as legs, arms, head. Not necessarily animation controls, but ACTION controls specific to body part. Leg action control would then contain several clips that are based on walking, running, falling. Combination of these controls would result with numerous mix of animation.
A thinking-node is a basic conditional type function which takes the input of certain attributes or another node and calculates them in a user-specified way. Thinking nodes can blend several actions together or determine which action is appropriate or has a higher priority, again depending on the user. Thinking nodes also can be made to be specific for a certain action only.
The brain node takes all its inputs coming from several thinking nodes, and makes a list of actions to be applied to the agent.
Example1:
Lets say we got a thinking node which determines where the agents eyes should be looking at, and another thinking node which takes control of the direction the agent is aiming with its weapon. The brain then compiles a list which will look something like:
ActionCtrl “eyesController -perform lookAt(-20,-10,50)”
ActionCtrl “aimController -perform aimSniper”
The brain node will then start performing these actions and go through the nodes again once they are done. Controllers need an action to perform and some attributes if needed as shown in the list compiled by the brain node. The list compiling just makes it easier to perform actions and have the attributes needed for those actions ready instead of going through the thinking nodes and finding which attribute is needed.
But then WHAT IF you want the agents to be smarter? What if lets say, in the middle of performing a Running action, a big wall suddenly appears in front of the agent. We can solve that by having runtime thinking-nodes which checks the actions being performed by the agents and makes sure they are still valid.
Another thing to think about is heirarchies and priorities. Which actions have more importance than the other and which actions affects other actions. Since this isnt going to be a full on complete AI controlled system where each agent is capable of thinking on its own and able to do everything (like an advanced bot), its going to be easier since the user can make simpler agents that do only a certain amount of things and have specified heirarchies and priorities.
Anyway I just woke up, so I hope I made sense. This is really interesting however, AI and animation, makes me wanna make my own crowd sim for fun hehe.
It seems like the impotrant part is having a good scene graph and then worry about updating it efficiently afterwards.
Simon
Good Question. MDuffy? Hugh? Would this stuff be under design patterns or something similar?
I haven’t run across any overall document on node based architecture. You’ll have to pick up bits and pieces here and there, and then combine them to create the framework you want.
For design patterns, I used the book Design Patterns by Gamma, Helm, Johnson, and Vlissides. You probably won’t use any single patterns exclusively, but will use them as ideas on how to handle certain challenges. I use the Iterator pattern to access my nodes, the State pattern to define what the node types are, and I think I use an Observer pattern to keep iterators and smart pointers up to date.
I rely on the book “Algorithms” by Robert Sedgewick a lot when I’m needing to figure out how to traverse a graph efficiently, or handle tasks that computer scientists have studied. For example, the pseudo code in that book served as the backbone of the Regular Expression parser I wrote a few weekends ago (couldn’t find a good cross-platform regular expression parser that met my needs… had to write my own). “Algorithms” has some node/tree traversal code in there, and I’d recommend the book without hesitation.
Some node traversal code is under the topic of Graph Theory, but there is a lot of work in this field and not all of it will apply.
You will also figure out how you want to design the node system based on your experience with other packages. My node system shares some overall design similaries with Maya’s node graph, but will be traversed an entirely different way than how Maya approaches it internally. I also learn pros and cons of different design approaches by looking at how Houdini, Modo, Dark Tree, Slim, compositing packages, and other software handle node approaches. Heck, my storage format is even similar to Lightwave’s LWS format, except that it is in XML and addresses the shortcomings of LWS that make it difficult to work with.
So I haven’t found any all-in-one source reference for node based coding, but rather a lot of different sources that I can take one or two ideas from. There aren’t any revolutionary new ideas in my code… just hopefully good implementations of common knowledge. You just have to look around and see how others do it, take the good ideas, leave the bad ideas, avoid patented ideas, and come up with something of your own.
Cheers,
Michael Duffy
Woaahh!! Cheers for the responses!! :eek: Haven’t seem this thread for a while and there’s loads to investigate!!
I agree with MDuffy about the design patterns book by Gamma (et al). Very useful for all types of problems, plus very easy to pick up for a good read!
In terms of node-based architectures, probably the best documentation I found was the Shake SDK docs (pointed to me by Hugh, cheers!!
) that include how their node engine works and how the ‘push-pull’ driven part of the network works in relation to dependencies and re-evaluating nodes, etc. A good read if you can get it! Also, the Maya DG is a another good example and the API docs or one of the many books of the API are usually good for a indepth explanation.
For my own use (i.e brain nodes, neural net stuff) I’m starting to look into ‘Motivational Graphs’ (from a article in AI Prog Wisdom 2) if anyone’s heard of them?
Pretty much everything I would have said has been said already…
I’ve never properly developed a node-based system, so pretty much all I know is from using other APIs… These being Maya and Shake…
I’d recommend Complete Maya Programming, which has some great info on Maya’s DG, and also, as Dan mentioned, the Shake SDK docs…
Just another related question. If you want to ignore a node, what do you do about it’s upstream connections? Should it block, pass through, or have the option of either?
And if you do have it pass through, but have different data types (ie colours and floats in a hypershade like application), how would you handle the conversion? (max. min, avg, luminance etc??). Do you need some sort of temporary override conversion node?
Simon
If a node is ignored, all connections should just pass through…
Actually, I just re-read your post… I didn’t realise that you were working with multiple data-types in your tree… in that case, I’m not sure…
You could have a generic conversion for each type which is used when you ignore a node, but ideally, ignoring should only be allowed when the input and output types are the same…
this is more a post so I can remember these resources, but these seem useful:
Gamasutra article (mentioned in another cgtalk thread)
http://www.gamasutra.com/features/20030829/vanderbeek_03.shtml
Online Data Structure and Algorithm books in several languages (C++, C#, Python, Ruby)
http://www.brpreiss.com/
A Perl DAG module (personally I love Perl, but may not be exactly what you are looking for)
http://www.perlmonks.org/index.pl?node_id=153259
Simon
Haven’t had time to read all posts in detail, so please excuse if I repeat something.
The “Design Patterns” book by Gamma et al. (also known as “Gang of Four” or GoF) is the best book you could get. I was about to recommend it myself but MDuffy beat me to it 
The patterns that you would need to construct a DAG (directed acyclic graph) is the ‘Composite’ pattern.
Creating the GUI should be a completely separate concern. Have a look at the ‘Model View Controller’ or MVC pattern (not in the GoF book but should be widely available on the net; it’s been first written down in Smalltalk). I wouldn’t worry about things like moving things around onscreen before everything related to passing data up and down the graph itself works.
A more advanced pattern for complicated data passing you could take a look at would be ‘Bureaucracy’ (search for it on the net), but you should have a good understanding of the GoF patterns before getting into this one.
Updating the graph using ‘Observer’ is a good choice.
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.