属性#

‘Capture Attribute’ nodes are inserted automatically when required

Be sure to be familiar with fields: Blender reference documentation.

Geometry property#

Fields such as Index or Position represents a value (Integer, Float, Vector…) associated to a domain (Point, Edge,…) of a geometry.

In a Blender tree, the geometry a field belongs to is found by following the links forwards and backwards (see Blender Field).

A field is a geometry property

In geonodes, fields are implemented as properties of class Geometry. In the following example (extracted from Blender documentation), we use two fields of input geometry: Index and the Position.

import geonodes as gn

with gn.Tree("Geometry Nodes") as tree:
    
    geo = tree.input_geometry
    
    v = geo.position
    v = v.scale(scale=geo.index)
    
    geo.set_position(offset=v, node_color="green")
    
    tree.output_geometry = geo

In the resulting tree, Position and Index nodes are fields of the input geometry because their links “join” at the green node ‘Set Position’:

Let’s add another ‘Set Position’ node after the second one, fed by the same offset input. This second node is colored in blue.

import geonodes as gn

with gn.Tree("Geometry Nodes") as tree:
    
    geo = tree.input_geometry
    
    v = geo.position
    v = v.scale(scale=geo.index)
    
    geo.set_position(offset=v, node_color="green")
    geo.set_position(offset=v, node_color="blue")
    
    tree.output_geometry = geo

THE RESULTING TREE IS NOT THE FOLLOWING

In the tree above, the fields Index and Position are evaluated twice, one for the green node and one for the blue node. These two nodes are fed by two different geometries, hence the fields Index and Position take different values.

The tree resulting from the second script is the following:

Since the python script defined the index and position as property of the initial geometry (v = geo.position), it understand that a ‘Capture Attribute’ node is necessary to feed the blue node.

On the illustration below, we can see the three resulting meshes with the same default cube as input:

‘Capture Attribute’ insertion#

geonodes module inserts ‘Capture Attribute’ nodes whenever required. As a consequence the second tree will never be generated by geonodes:

To produce this result, you must explicitly get the index and position of the transformed geometry as illustrated below:

import geonodes as gn

with gn.Tree("Geometry Nodes") as tree:
    
    geo = tree.input_geometry
    
    # Fields from the initial geometry
    
    v = geo.position
    v = v.scale(scale=geo.index)
    
    geo.set_position(offset=v, node_color="green")

    # Fields from the transformed geometry
    
    v = geo.position
    v = v.scale(scale=geo.index)

    geo.set_position(offset=v, node_color="blue")
    
    tree.output_geometry = geo

The resulting tree is the following.

There is not anymore ‘Capture Attribute’ node because it is useless, but there are now two ‘Index’ nodes and two ‘Position’ nodes, one for each geometry.

from imare import *
init_modules(__file__, "imare", "geonodes")
flush_data()

import geonodes as gn
from geonodes.nodes import nodes
import numpy as np

rad = np.radians

with gn.Tree("Geometry Nodes", reroute=False) as tree:

    geo = tree.input_geometry

    v = geo.position.scale(scale=geo.index)

    geo.set_position(offset=v, node_color="yellow")

    v = geo.position.scale(scale=geo.index)

    # 连续的`set_position`会新增`capture_attribute``
    geo.set_position(offset=v, node_color="light red")

    tree.og = geo

Tree({
    O.cube @ "Cube": {
        Mod.geometry_nodes: {
            "node_group": "Geometry Nodes",
        },
    },
}).load()