Blender Pythonを使用して外部データを読み込みGeometry Nodeで使用する

Pythonを使用して外部データを読み込みGeometry Nodeで使用する

GeometryNodeのみでは、CSVなどの外部データを読み込むことができません。外部データを使用したい場合は、Pythonで事前にデータを読み込んだ点群を作って、それをGeometryNodeで使用する方法がいいかと思われます。

Pythonによるデータ読み込みの簡単なサンプル

Blender上に4点を作成する簡単なサンプルです。 その4点に10から40までの値(dummydata)を与えています。

import bpy
 
# make mesh
vertices = [(10, 0, 0),(0, 10, 0),(-10,0,0), (0,-10,0)]
edges = []
faces = []
plotDataMesh = bpy.data.meshes.new('plot_data')
plotDataMesh.from_pydata(vertices, edges, faces)
attr = plotDataMesh.attributes.new("dummydata", 'FLOAT', 'POINT')
dummyData = [10,20,30,40]
attr.data.foreach_set("value", dummyData)

plotDataMesh.update()

# make object from mesh
plotDataObject = bpy.data.objects.new('plot_data_object', plotDataMesh)

curScene = bpy.context.scene
curScene.collection.objects.link(plotDataObject)

このスクリプトを実行し、アトリビュートをGeometryNodeから見るとdummydataのフィールドにdummydataというフィールドがそれぞれ値が入っていることが分かります。

GeometryNodeからはNamedAttributeのノードを使用してデータを活用します。

世界の人口数をビジュアライズしてみる

次に以下のページで公開されていた世界の人口データをPython+GeometryNodeで映像化します。

City, Latitude, Longitude, Country, Population · GitHub

コードはこのような形になります。先ほどのものにCSVを読み込む部分を追加した形です。

import bpy
import os

class population_data(object):
    city = ""
    country = ""
    longitude = 0.0
    latitude = 0.0
    population = 0

def load_csv_population_data(fileName):
    dataSet = []
    ### load csv
    curDir = os.path.dirname(bpy.data.filepath)
    dataFilePath = os.path.join(curDir, fileName)
    if os.path.exists(dataFilePath) :
        f = open(dataFilePath, "r")
        for line in f.readlines():
            parts = line.strip().split(",")
            if len(parts) == 5:
                data = population_data()
                isValid = True
                try:
                    data.city = parts[0]
                    data.latitude = float(parts[1])
                    data.longitude = float(parts[2])
                    data.country = parts[3]
                    data.population = float(parts[4]) / 10000.0
                except:
                    isValid = False
                if isValid:
                    dataSet.append(data)
    return dataSet
 
vertices = []
edges = []
faces = []
populations = []
for data in load_csv_population_data("data.csv"):
    vertices.append((data.longitude, data.latitude, 0.0))
    populations.append(data.population)
 
# make mesh
plotDataMesh = bpy.data.meshes.new('plot_data')
plotDataMesh.from_pydata(vertices, edges, faces)

attr = plotDataMesh.attributes.new("population", 'FLOAT', 'POINT')
attr.data.foreach_set("value", populations)

plotDataMesh.update()

# make object from mesh
plotDataObject = bpy.data.objects.new('plot_data_object', plotDataMesh)

curScene = bpy.context.scene
curScene.collection.objects.link(plotDataObject)

これを実行すると以下のような点群が生成されます。 populationフィールドを使用して、縦棒グラフを作成するGeometryNodeは以下のようになります。

アトリビュートを使用してShaderで色付けします。

完成したものがこちらになります。

まとめ

BlenderPythonは点群を作るだけであれば、非常に高速で、この組み合わせはデータビジュアライゼーションにおいて、他のソフト(Maya、Houdiniなど)に対しても十分なアドバンテージがあるように思います。 このブログがなんらかの参考になれば幸いです。