0
$\begingroup$

I add Geometry Nodes to the default Cube but instead of using its geometry I use a Curve Line: enter image description here How to get this Curve Line data with bpy? I've tried the following and failed:

  • bpy.context.object.data.splines - raises ValueError, because the initial object type is Mesh which doesn't have splines attribute.
  • ob = bpy.context.object.evaluated_get(bpy.context.evaluated_depsgraph_get()) and ob.data.splines - raises the same Error
  • in bpy.context.evaluated_depsgraph_get() I could not find anything related to the object special types, except instances

For this particular example the data can be partially obtained by accessing bpy.data.node_groups['Geometry Nodes'].nodes['Curve Line'].inputs, but if the curve has further processing e.g. resampling with Resample Curve, offsetting points locations with Set Position node and Noise Texture, randomizing, converting to mesh, processing and converting back to curve, etc. - it becomes harder and harder to track and reproduce in Python the final data of the curve in this way. So is there a way to get this data directly?

By the data I mean points locations, tilt, radius, handle types and handle points location, etc.

$\endgroup$
2
  • 2
    $\begingroup$ I don't think it is directly possible. GN result is a mesh. Nearly the same subject as blender.stackexchange.com/questions/288685/… So you can store what you need as attributes and get them once evaluated. $\endgroup$
    – lemon
    Commented Mar 23, 2023 at 8:32
  • 1
    $\begingroup$ maybe "as a workaround" you could write a python script, which just copies your object for every frame and then applies the GN modifier and then you could convert it to a spline...maybe that helps? $\endgroup$
    – Chris
    Commented Mar 23, 2023 at 8:51

1 Answer 1

3
$\begingroup$

A way to do it is to hack the geometry nodes tree.

I propose to hack the tree output (but you may need to hack it somewhere else?).

Say we have this simple setup:

enter image description here

We want to insert a "hack" node group just here, using Python:

enter image description here

And remove it with script after you've retreived the wanted data.

The hack node tree is the following (get the attribute you want, name them appropriately, etc.):

enter image description here

The code

import bpy

def insert_hack(target, hack_name):

    # find the hack
    hack = bpy.data.node_groups.get(hack_name)
    if not hack: return False

    # find the output
    output = None
    for node in target.nodes:
        if node.type == 'GROUP_OUTPUT':
            output = node
            break

    # if output not found or has no link exit
    if not output: return False
    input0 = output.inputs[0]
    if not input0.links: return False

    # insert the ack
    hack_group = target.nodes.new('GeometryNodeGroup')
    hack_group.node_tree = hack
    
    link = input0.links[0]

    # link it
    target.links.new(link.from_socket, hack_group.inputs[0])
    target.links.new(hack_group.outputs[0], output.inputs[0])
    return True

def remove_hack(target, hack_name):

    # find the hack
    hack = None
    for node in target.nodes:
        if node.type == 'GROUP' and node.node_tree.name == hack_name:
            hack = node
            break
    if not hack: return False

    # relink the output
    from_socket = hack.inputs[0].links[0].from_socket
    to_socket = hack.outputs[0].links[0].to_socket
    target.links.new(from_socket, to_socket)

    # remove the hack
    target.nodes.remove(hack)
    return True

target_gn = bpy.data.node_groups['GN']

insert_hack(target_gn, 'Hack')

try:
    target_ob = bpy.data.objects['Cube']
    #target_ob = bpy.data.objects['BezierCurve']

    depsgraph = bpy.context.evaluated_depsgraph_get()

    target_ev = target_ob.evaluated_get(depsgraph)

    target_me = target_ev.to_mesh()

    positions = target_me.attributes.get('positions')

    for data in positions.data:
        print(data.vector)

finally:
    remove_hack(target_gn, 'Hack')

Which outputs

<Vector (1.0000, 0.0000, 0.0000)>
<Vector (0.9808, 0.1951, 0.0000)>
<Vector (0.9239, 0.3827, 0.0000)>
<Vector (0.8315, 0.5556, 0.0000)>
<Vector (0.7071, 0.7071, 0.0000)>
<Vector (0.5556, 0.8315, 0.0000)>
<Vector (0.3827, 0.9239, 0.0000)>
<Vector (0.1951, 0.9808, 0.0000)>
...

Note:

If the base object is a curve, there is no need to use the "Curve to Mesh" node in the hack. But if the base object is a mesh, this is needed (as if not, the attributes are not kept).

$\endgroup$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .