Archive 17/01/2023.

Iogram Core is now Open Source

godan

Yep, as of this release, the entire Node Graph and Geometry libraries are now totally open source. Also, we’ve released all the 150+ core components that are accessible via the Editor.

There is also a brand new Iogram release for Windows, OSX, and Linux available here.

https://youtu.be/hdOY9ktaWtQ

hdunderscore

The library looks like a real gem, big thanks for sharing the source ! I was recently looking for something similar to the geometry library you’ve shared, and I had trouble finding anything similar.

Eugene

Great work!
However, your Iogram really, really, really needs detailed text documentation and lessons. It is very puzzled and videos almost don’t help.

godan

@Eugene Yes, it certainly does! In fact, this week we are making a big push with the documentation/tutorials.

rku

What is the practical application of this? It looks cool and all but i have no idea what it could be used for.

godan

@rku I guess the main goal with Iogram is to make the best possible prototyping environment for 3d models, apps, and games. To me, this means a few things:

  1. No black boxes. Open source only please. There is nothing worse than getting a great prototype working with 3rd party code, and then not being able to actually bring the project to market do to licenses, cost, lack of support, lack of features, etc…

  2. Levels of Abstraction. Sure, sometimes I want to dig in to the guts of the rendering system, or deal with issues arising from floating point precision (boolean operations, I’m looking at you!). Most of the time, however, I just want to test my idea as fast as possible. I want to work with a rich set of components that let me figure out if what I want to do is easy/hard/impossible.

  3. Explore families of solutions, rather than single instances I personally find it very difficult to start with a blank text file and code up exactly what I want perfectly, the first time. Instead, I find it far more effective to write modular systems and tweak their parameters, and find that perfect mix of values through exploration. There is actually a bunch of literature on this stuff (check out this talk by Brett Victor).

So, that’s the plan! We certainly have a ways to go, but I think this latest release is a pretty good step in the this direction. Would love to hear any thoughts on this!

hdunderscore

The tool kind of reminds me of Houdini, and probably is useful to a similar audience. It might help to use similar terms as Houdini when describing Iogram.

Just playing with it a little – I definitely need to see those tutorials :smiley:

sabotage3d

It looks like Houdini SOPs but in realtime context. Looks pretty cool. Thanks for sharing.

smellymumbler

I’m so curious about how you handled the architecture behind this! I was working on something similar a few weeks ago, but more inspired by Houdini. Of course, my implementation was very naive and i started with a small noise texture generator created with nodes.

The way i did it was, basically, a tree of nodes that i walked from the root. The root was always one output. From that, i walked to all leaves, checking if the node was runnable (by checking if all required ports were connected), and ran an execute() method on the nodes. Each node implemented the execute() method differently. My actual execute() code was just building a virtual shader, literally by copying shader code strings to a buffer. When i was finished with all nodes, i just executed the shader code.

Could you elaborate on your approach? It would be very enlightening to see other approaches on this. My approach seems very hackish, but i never found a better way of doing it.

godan

@smellymumbler Hey, for sure. In fact, I can refer you directly to the source!

In our approach, we have three main classes for the Node Graph:

  1. IoGraph - handles node add/delete, link add/delete, and solving the graph.
  2. IoComponentBase - the base class for inheriting nodes that do particular things. There are a bunch of important functions in this class, but by far the most important is the SolveInstance. This handles what exactly the node does.
  3. IoInputSlot and IoOutputSlot - these classes handle what kind of data is passed to SolveInstance, and the level of DataAccess (i.e. Item, List, Tree).

So, to interact with the NodeGraph, you would create some custom nodes from IoComponentBase and then add them to the graph, along with some connections, and add some data at the exposed input slots. Here is an example from one of the tests:

	Context* myContext = new Context();

    //the data
	Vector<Variant> someFloats;
	someFloats.Push(7.0f);
	someFloats.Push(9.0f);
	someFloats.Push(11.0f);
	someFloats.Push(13.0f);
	someFloats.Push(15.0f);
	someFloats.Push(17.0f);

    //push data to data tree
	IoDataTree tree0(myContext, someFloats);

    //create graph object
 	IoGraph g(myContext);

    //create the Mass Average component
	SharedPtr<IoComponentBase> averager(new Maths_MassAverage(myContext));
	g.AddNewComponent(averager);

    //add the data tree input at component index 0, input slot index 0
	g.SetInputIoDataTree(0, 0, tree0);

    //solve using topological sorting
	g.TopoSolveGraph();

   //collect data
	IoDataTree outTree(myContext);
	g.GetOutputIoDataTree(0, 0, outTree);

We use a topological sorting algorithm that orders that orders the nodes by their rank (i.e. how many edges away from being a root node). Then, you can loop through the nodes and call the Solve methods.

smellymumbler

Very interesting! Thank you so much for the detailed explanation. I’ll dedicate some time to read and understand the codebase, it’s really well written.

I’ve noticed that you’re passing the scene to the graph: https://github.com/MeshGeometry/IogramSource/blob/master/Player/IogramPlayer.cpp#L159

Is that how the components manipulate textures and geometry? You pass the scene and then, on the solve method, each component manipulates a part of the scene?

Also, what is the purpose of the PreLocalSolve() methods?

godan

Hmm, I think passing the scene to graph is deprecated. Rather, I use the context variable (i.e. GetGlobalVar) “Scene” to get an active scene. This is probably not great.

PreLocalSolve() is an interesting one. The problem is that some graph nodes create state. For instance, the AddNode component adds a (scene) node when it is run. But without any other handling, this would very quickly create lots and lots of nodes. So, the PreLocalSolve() function is there so that components can implement a way to handle their state. In the AddNode case, PreLocalSolve() deletes all the nodes it created during the last TopoSolveGraph().

ghidra

@godan this is super cool stuff.
Looking at the code, i noticed that the license at the top of each file seems to mirror urhos.
To be clear, is it MIT?

godan

Yes, it is MIT. I guess we could probably state that somewhere, but I think the terms of the license are pretty clear (and more important than the name of the license). Also yes, the goal was to mimic Urho’s license. Please let me know if I messed it up somehow!

slapin

Can you please provide build instructions? I don’s see root CMakeLists.txt, so I wonder…

godan

Ah right. I suppose you will need that :slight_smile: I think each folder (i.e. Geometry, Core, etc) has it’s own CMakeList, but I will create one that builds everything.

godan

@Eugene @hdunderscore We now have some documentation and some tutorials! There is more to come, but it would be great to know if this is helpful.

hdunderscore

I have read through some of the getting started documentation, it definitely helps !

I think there are some things that you might be able to look into UI-wise, eg: Highlighting things should give visual feedback, dragging the nodes from the list to the graph should give some visual feedback (easiest thing might be to dim all the windows except for the graph and/or change the mouse icon).

I didn’t realise before I read the documentation that you could right click on the node inputs/outputs.

Nice work :smiley: