I have data in a .csv in the form of:

Frame # P0 Z Height P1 Z Height P2 Z Height ... P19 Z Height
1 19.23 24.43 84.94 ... 83.27
2 12.43 21.33 24.44 ... 53.21
... ... ... ... ... ...
300 49.23 24.43 84.94 ... 83.27

What I would like to do is make a 4x5 grid of points, and adjust each point's Z position based on a lookup into this table each frame.

For instance: the vertex with index 0 should have a z position of 12.43 on frame 2.
I've used Simon Broggi's Spreadsheet Data Importer to get Named Attributes for each of the points like this: enter image description here enter image description here

I'm having trouble figuring out how to select by named attribute off of an index. I've gotten selecting by index working and set position working, but I don't know how to grab the value for say "Frame 13, Position 7" and get 233.983 back in order to set the position of Point 7.

Does anyone have any pointers? I'm new to geo nodes and the data flow is hard for me to understand.

  • $\begingroup$ Hi. Is the object that has the GN modifier the object that has the imported CSVs? (Group Input > Geometry). In the node tree you use the geometry of this object with the joined geometry of the grid for the Sample Index node. I would just use the Group Input > Geometry. Also you use the Named Attribute 'VALUE'. But according to screenshot 1 the columns are named '1', '2', '3', '4'... There is no column named 'VALUE'. Next challenge is to do this x times for all needed columns without a loop (Blender 4 supports loops) $\endgroup$
    – Blunder
    Aug 18, 2023 at 21:44

1 Answer 1


I think your approach is not the best, because either you add a "named attribute" node for each named attribute, which means for each frame of the animation [ouch], or you use current frame to evaluate strings, to pass them as attribute names (but strings don't support fields, which is a limitation…). Meanwhile, you can just load data as vertex positions, and operate on that, so this is the workflow I'll present.

If we have some csv file, for example comma delimited coordinates of a rotating triangle:

from math import cos, sin, tau
with open("E:/file.csv", "w") as f:
    for i in range(300):
        for j in (0, 1/3*tau, 2/3*tau):
            x = round(sin(i/100+j), 3)
            y = round(cos(i/100+j), 3)
            print(x, y, .0, sep=',', file=f)

I won't paste the whole file here, instead here's how it's supposed to be read:

frame0 vert0 x, frame0 vert0 y, frame0 vert0 z 
frame0 vert1 x, frame0 vert1 y, frame0 vert1 z 
frame0 vert2 x, frame0 vert2 y, frame0 vert2 z 
frame1 vert0 x, frame1 vert0 y, frame1 vert0 z 
frame1 vert1 x, frame1 vert1 y, frame1 vert1 z 
frame1 vert2 x, frame1 vert2 y, frame1 vert2 z 
frame2 vert0 x, frame2 vert0 y, frame2 vert0 z 
frame2 vert1 x, frame2 vert1 y, frame2 vert1 z 
frame2 vert2 x, frame2 vert2 y, frame2 vert2 z 
frame3 vert0 x, frame3 vert0 y, frame3 vert0 z 
frame3 vert1 x, frame3 vert1 y, frame3 vert1 z 
frame3 vert2 x, frame3 vert2 y, frame3 vert2 z

Now we can load that to a numpy array and efficiently add a new mesh with the correct number of vertices and set their positions:

import numpy as np
from bpy import context as C, data as D

coords = np.loadtxt("E:/file.csv", delimiter=',', dtype=np.float32)
me = D.meshes.new('data_mesh')
coords = coords.flatten()  # foreach_set always expects 1-dimensional array
me.vertices.foreach_set('co', coords)
ob = D.objects.new('data_object', me)

And now this new object can be loaded to geonodes, or geonodes can be applied on that object. Then positions can be sampled on the vertices according to some formula:

The example is not astonishing, but it works:

You could do various stuff with this data now, for example you can use geometry proximity to find out which 'vertex' (in quotes, because it's technically a vertex, but it's just there to hold data about position of the actual vertex) is the closest to a given position, and then the obtained index modulo 3 will give you the index of the (actual) vertex, and floor(index/3) will give you a frame on which this vertex was at that spot. You can't do stuff like this using named attributes…


You must log in to answer this question.

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