9
$\begingroup$

I have some data with cartesian coordinates + some attributes (e.g. size, rotation, and/or color) outside blender and want to use that as basis for geometry nodes. For example, I want to use the vertices as instances for cubes or spheres and use additional attributes to scale/rotate/etc the instances accordingly.

Is it currently possible to read in the data from a file (e.g. csv, ply, etc.) into geometry nodes maybe by using the import functions or by using the python API with a small script?

At the moment I save the data into a .ply-file with properties x, y, z, red, green, blue, so I have the points. However, using the red, green, and blue property seems useless without using faces and I end up with the vertices which I can instance, but not transform.

Maybe it would also be possible to import the data in two steps.

  1. One x-y-z file with the actual vertices
  2. Additional information given in another file with x-y-z information, but with the meaning of attr1, attr2, attr3.
    • using this additonal geometry for the actual object (e.g. distance from the origin for size) and
    • removing the geometry from the final result again (which I don't know at the moment how to do; probably something with join geometry first, then at the end with point separate and some condition evaluated before)
    • This seems a bit complicated though.
$\endgroup$

1 Answer 1

9
$\begingroup$

Edit: This does not seem to work anymore with Blender/Geometry Nodes 3.0+.

The csv file can be read into blender with python. By using the blender API the data can then be assigned to an attribute which is accessible also in Geometry nodes.

From Python : Custom Attribute for Vertices I got the piece of code how to set an attribute.

import bpy
import csv
import numpy

filepath = "blender_GN_test.csv" # 4 comma-separated columns without header
csvfile = open(filepath, 'r', newline='')
ofile = csv.reader(csvfile, delimiter=',')
verts = []
s = []

for row in ofile:
    verts.append(Vector((float(row[0]), float(row[1]), float(row[2]))))
    s.append(float(row[3]))

csvfile.close()


obj_name = "MyObj"
mesh_data = bpy.data.meshes.new(obj_name + "_data")
obj = bpy.data.objects.new(obj_name, mesh_data)
bpy.context.scene.collection.objects.link(obj)
mesh_data.from_pydata(verts, [], [])

scale = numpy.array(s)

obj.data.attributes.new(name='scaleVec', type='FLOAT', domain='POINT')
obj.data.attributes['scaleVec'].data.foreach_set('value', scale)

Here is the very simple Geometry node setup. I added a simple icosphere as instance object: enter image description here

Here is the result with some data based on cosine and sine calculations for z and for scale which I read from the csv-file.

enter image description here

Edit: Thank you 'TheJeran' for finding out to set foreach_set('value', scale) when type='FLOAT'. (see comment at the answer here: Python : Custom Attribute for Vertices)

You can also set a vector with

some3Dvector = numpy.array(s * 3) # or 3 vectors read by the csv into the numpy.array
obj.data.attributes.new(name='scaleVec', type='FLOAT_VECTOR', domain='POINT')
obj.data.attributes['scaleVec'].data.foreach_set('vector', some3Dvector)
$\endgroup$
1
  • $\begingroup$ Thank you, this was really useful, i just came on to comment that to get this to work (as a complete newcomer to Python and Blender scripting) I had to import mathutils and use mathutils.Vector(...), as the Vector class wasn't being recognised. $\endgroup$
    – awnine
    Apr 27 at 16:28

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.