User-defined geometry node with Python classes
The capability of the geometry node system is limited by the pre-defined node types. This has two implications:
- Some things may not be possible with geometry node, for example generating an arbitrary mathematical surface
- Some things are possible, but are tedious and error-prone.
For example, if I want to setup the geometry node to solve quadratic equations, I need to add, arrange, and configure a bunch of math nodes. This is a time consuming processing, and it might be hard to identify if there is a mistake.
Now suppose I have the following Python code:
# Blender would provide a class like this
class NodeSlot:
def __init__(self, data_type, name):
self.data_type = data_type
self.name = name
# The user defines this class. `UserDefinedNode` is some base class provided by Blender.
class QuadraticEqNode(UserDefinedNode):
def __init__(self):
# Define input and output slots. I imagine there would be an API in the base class.
self.define_slots(input_slots=[
NodeSlot(float, "a"),
NodeSlot(float, "b"),
NodeSlot(float, "c"),
], output_slots=[
NodeSlot(float, "solution 1"),
NodeSlot(float, "solution 2"),
])
# The user defines how the node calculates its output.
def execute(self, data_input):
a = data_input[0]
b = data_input[1]
c = data_input[2]
delta = math.sqrt(b * b - 4.0 * a * c)
return ((-b + delta) / (2.0 * a), (-b - delta) / (2.0 * a))
And imagine I could add a custom node like this:
and I could choose my implementation of this node. The node would automatically have slots according to my definition:
This is not only easier to write and read (because I write the calculation explicitly, just like writing math), but more importantly this can be tested , automatically if necessary (because it's just a class), and thus ensure correctness.
In this mockup I have used floats for all the slots. I imagine other data types such as mesh, curve, etc. should also be supported.
Solving quadratic equation might not be the best example for this idea because it could be done with the current geometry node system. But this capability would be invaluable in data visualization.
I once had a project to render visualizations of the Lorenz attractor, which is a mathematical curve defined by a set equations. In that project I solved the equations using some other programs (Mathematica) and saved the curve as a set of points in a text file. I then wrote a Python script in Blender to read that text file, and construct the curve object. That project was acutally used in a college class as teaching material.
The process could be simplified by solving the equations in Python in Blender, and completely forego the text file. But this is still not ideal, because if I need to adjust the parameters of the equations, I would need to remove the existing curve object, change the parameters, and rerun the script. I lose all the edits (e.g. modifiers) on my original curve. This problem would be non-exist with a custom node system described above.
Possible cons: performance? I have never read the Blender code, but I assume the pre-defined nodes are written in native code, which could be an order of magnitude (or more) faster than Python code.
14 Comments
I think this would be really useful. My main use case is when there's no geometry node for what you need, you could just write some python to do it
I'm the dev of QuadRemesher addon, and I would like to implement QuadRemesher as a GeometryNode. So I'm looking for this feature as well !
This will open to unlimited possbility of nodes and plugins, just like GhPython in Grasshopper. I would very much love this feature!!!
This would be amazing. I hope this gets implemented soon.
This would be really cool! Ideally, this node would accept any inputs, including geometry or instances.
would like to use numpy and more with it
I am hoping for exactly this this since geometry nodes first came out! I know two other softwares (Grasshopper in Rhino and Touchdesigner) which do have exactly that way of embeding coding into a node based environment and it has proven very very useful to me for more complex node systems!
As a dev on Building Tools addon, this feature would be very useful to make our addon procedural.
Looking forward to this.
For the above example, I would add another output node: discriminant (b^2-4ac); so users of the node can tell if the equation has none, one, or two real solutions. The discriminant is already comped, hence is 'free', does not add extra computation time. This output node and the two solution nodes are 'optional', users do not have to use all of them.
One use case of such node is when we just want to know if a circle intersects other line or not, or if it is tangential; we may not need to know the actual intersection points.
I am looking forward to this feature.
Having an API to implement custom Python nodes for Blender would be a game-changer. I'd be very curious to hear from the team about performance and memory considerations. For some use cases though, it could possibly give a significant advantage, having access to the internal data structures of geometry through the Blender API.
As an example case that I'd be interested to explore is implementing a custom node that generates new geometry based on existing geometry. Right now I have to work with nested For/Each or Repeat zones, which gets slow very fast. I could imagine this to be a great use case for an initial implementation.
I have noticed that there is git branch from Snowdaw, github.com/Snowdaw/blender-python-geometry-node that appears to be an implementation of this request. Does anyone have any experience using this branch?
Since Python has limitations around threading and performance, could we build this using a native C/C++ extension server, with a named pipe for control and a memory mapped file for data exchange (or any other simular high performance interop)?
Does anyone know if any one has tried building this already?
Python API access to Geonodes would open up the world of a lot more possibilities than making tedious geometry nodes groups, so really looking forward to this as well
I'm eagerly awaiting this.