ラベル BlenderPython の投稿を表示しています。 すべての投稿を表示
ラベル BlenderPython の投稿を表示しています。 すべての投稿を表示

2025年10月27日月曜日

技術メモ BlenderPythonの「Runtime Error:csvに列IDがありません」の解決

 Technical Note: Fixing BlenderPython's "Runtime Error: CSV file contains no column ID"


I'm using a BlenderPython script that plots CSV files containing data on tens of thousands of artifacts (IDs, xyz coordinates, and numerous attributes) as vertices in the Blender3D viewport within a second. However, the other day, I suddenly got the error "Runtime Error: CSV file contains no column ID," and was unable to plot. I've written a note about how to fix this.


数万遺物データを格納したcsvファイル(ID、xyz座標、多数の属性)を、Blender3Dビューポートに1秒以内に頂点としてプロットするBlenderPythonスクリプトを重宝して活用しています。ところが先日突然、「Runtime Error:csvに列IDがありません」が出て、プロットできなくなりました。その解決策をメモしました。

1 エラーの様子


遺物プロットに使っているBlender画面(2画面用にカスタマイズ、右端コンパートメントがBlenderPythonを記述したテキストエディター)

数万遺物データを格納したcsvファイル(ID、xyz座標、多数の属性)を、Blender3Dビューポートに1秒以内に頂点としてプロットできる優れモノのBlenderPythonスクリプトを毎日重宝して活用しています。ところが先日突然、「Runtime Error:csvに列IDがありません」が出て、プロットできなくなりました。csvファイルに異常は見つかりません。ID列は正常です。試しに列を入れ替えて、先頭列をxにしたところ、「Runtime Error:csvに列xがありません」が出てしまいます。

2 エラーの原因

ChatGPTに調査依頼してエラー原因を突きとめることができました。

BlenderPythonにおけるcsvファイル読込エンコードが encoding="utf-8"であるのに対して、csvファイルのエンコードが"utf-8-sig"であったので読み込めなかったのです。

自分はcsvファイルとExcelの間での文字化け回避などで"utf-8"と"shift-jis"の違いはいつも意識していたのですが、今回はじめて"utf-8-sig"というエンコードに直面して、エラー解決できなかったのです。"utf-8-sig"というエンコードのcsvファイルができたのは、2つのcsvフィアルを操作して1つの新しいcsvファイルを作成するPythonスクリプトをChatGPT支援で作った際に混入したことも判りました。

エラーとなったcsvをWZエディターで開き、文字コードを見ると、確かにUTF-8(BOM付き)になっています。


エラーとなったcsvファイルの文字コード

エンコード"utf-8-sig"のcsvファイルでは最初列名文字先頭に「BOM(Byte Order Mark)」という目に見えない文字(`\ufeff`)が入り、列名が\ufeffIDになり、スクリプトで指定した列名IDと異なり、エラーとなりました。

3 解決策

BlenderPythonスクリプトのcsvファイル読み込み部で、encoding="utf-8"をencoding="utf-8-sig"に修正して対処しました。これで"utf-8"のcsvファイルも"utf-8-sig"のcsvファイルも正常に読み込むことができます。

また原因がわかりましたので、同じエラーが類似BlenderPythonスクリプトで出た時は上記のように修正するか、csvファイルをWZエディターで読込み、"utf-8"に変更して書き出して使うことにします。


2024年4月28日日曜日

技術メモ BlenderPythonによるオブジェクトの干渉色塗色

 Technical memo

Interference coloring of objects with BlenderPython


I created a BlenderPython script with the help of ChatGPT that can paint selected objects with interference colors in Blender and make adjustments. The interference color scheme was developed by Koji Yamada.


Blenderで、選択したオブジェクトを干渉色に塗り、調整ができるBlenderPythonスクリプトをChatGPT支援により作成しました。干渉色配色はやまだこーじさん開発によるものです。

1 オブジェクトの例

次のオブジェクト(フォトグラメトリで作成した土偶3Dモデル)を例に説明します。


オブジェクト


オブジェクトのノード

以下、このオブジェクトに干渉色を塗色する手順をメモします。

2 オブジェクトのテクスチャ画像ノードを外す

オブジェクトのテクスチャ画像ノードをプリンシプルBSDFから外します。オブジェクトを選択します。


オブジェクトの様子


オブジェクトのノード

2 BlenderPythonスクリプト「干渉色ノード生成」をテキストエディターに読み込み、スクリプトを実行します。

BlenderPythonスクリプト「干渉色ノード生成」


import bpy

# 選択されたオブジェクトのアクティブなマテリアルを取得
obj = bpy.context.object
material = obj.active_material
nodes = material.node_tree.nodes

# テクスチャ座標設定
ndtc = nodes.new("ShaderNodeTexCoord")
ndtc.location = -1140, 350

# マッピング設定
ndmp = nodes.new("ShaderNodeMapping")
ndmp.location = -970, 350

# 波テクスチャ設定
ndtw = nodes.new("ShaderNodeTexWave")
ndtw.location = -800, 350

# グラデーションテクスチャ設定
ndgr = nodes.new("ShaderNodeTexGradient")
ndgr.location = -630, 350

# カラーランプノードの追加と設定
ndvr = nodes.new("ShaderNodeValToRGB")
ndvr.location = -450, 350
ndvr.color_ramp.color_mode = "RGB"
ndvr.color_ramp.interpolation = "LINEAR"

# やまだこーじさん開発干渉色カラーグラデーションの設定
ndvr.color_ramp.elements[0].position = 0.0
ndvr.color_ramp.elements[0].color = 0.949,0.996,0.984,1.000
ndvr.color_ramp.elements.new(position=0.042).color = 1.000,0.965,0.784,1.000
ndvr.color_ramp.elements.new(position=0.083).color = 0.961,0.784,0.369,1.000
ndvr.color_ramp.elements.new(position=0.125).color = 0.796,0.455,0.020,1.000
ndvr.color_ramp.elements.new(position=0.167).color = 0.490,0.000,0.627,1.000
ndvr.color_ramp.elements.new(position=0.208).color = 0.000,0.408,0.925,1.000
ndvr.color_ramp.elements.new(position=0.250).color = 0.000,0.757,1.000,1.000
ndvr.color_ramp.elements.new(position=0.292).color = 0.525,0.961,0.871,1.000
ndvr.color_ramp.elements.new(position=0.333).color = 0.863,1.000,0.522,1.000
ndvr.color_ramp.elements.new(position=0.375).color = 1.000,0.886,0.000,1.000
ndvr.color_ramp.elements.new(position=0.417).color = 1.000,0.620,0.482,1.000
ndvr.color_ramp.elements.new(position=0.458).color = 0.945,0.220,0.835,1.000
ndvr.color_ramp.elements.new(position=0.500).color = 0.604,0.259,0.984,1.000
ndvr.color_ramp.elements.new(position=0.542).color = 0.000,0.639,0.929,1.000
ndvr.color_ramp.elements.new(position=0.583).color = 0.000,0.882,0.694,1.000
ndvr.color_ramp.elements.new(position=0.625).color = 0.306,0.976,0.373,1.000
ndvr.color_ramp.elements.new(position=0.667).color = 0.839,0.925,0.412,1.000
ndvr.color_ramp.elements.new(position=0.708).color = 1.000,0.749,0.718,1.000
ndvr.color_ramp.elements.new(position=0.750).color = 1.000,0.498,0.902,1.000
ndvr.color_ramp.elements.new(position=0.792).color = 0.957,0.380,0.922,1.000
ndvr.color_ramp.elements.new(position=0.833).color = 0.616,0.561,0.788,1.000
ndvr.color_ramp.elements.new(position=0.875).color = 0.000,0.769,0.584,1.000
ndvr.color_ramp.elements.new(position=0.917).color = 0.000,0.890,0.510,1.000
ndvr.color_ramp.elements.new(position=0.958).color = 0.420,0.902,0.659,1.000
ndvr.color_ramp.elements.new(position=1.000).color = 0.812,0.820,0.816,1.000

# ガンマ設定
ndgm = nodes.new("ShaderNodeGamma")
ndgm.inputs[1].default_value = 2.2  # ガンマ値を設定
ndgm.location = -180, 350

# ノード間のリンク設定
material.node_tree.links.new(ndtc.outputs[0], ndmp.inputs[0])
material.node_tree.links.new(ndmp.outputs[0], ndtw.inputs[0])
material.node_tree.links.new(ndtw.outputs[0], ndgr.inputs[0])
material.node_tree.links.new(ndgr.outputs[0], ndvr.inputs[0])
material.node_tree.links.new(ndvr.outputs[0], ndgm.inputs[0])

# ガンマ設定ノード(ndgm)をプリンシパルBSDFにリンクする
# アクティブなマテリアルのプリンシパルBSDFノードを取得
principled_bsdf = None
for node in nodes:
    if node.type == 'BSDF_PRINCIPLED':
        principled_bsdf = node
        break

# プリンシパルBSDFノードが見つかった場合にのみリンクを作成
if principled_bsdf:
    material.node_tree.links.new(ndgm.outputs[0], principled_bsdf.inputs[0])
else:
    print("Principled BSDF node not found in material.")

3 オブジェクトが干渉色で塗色される

オブジェクトが干渉色で塗色されます。


オブジェクトの様子


オブジェクトのノード

ノードは左からテクスチャ座標、マッピング、波テクスチャ、グラデーション、カラーランプ、ガンマが生成し、プリンシブルBSDFにリンクします。

マッピングと波テクスチャはデフォルト設定になっていますので、干渉色塗色は望むような塗色になっていない可能性が高いので、調整が必要です。


マッピングと波テクスチャによる調整項目

カラーランプはやまだこーじさん開発干渉色の設定になっています。


干渉色設定のカラーランプ

ガンマはRGBのガンマ補正値2.2が設定されています。これは、BlenderのRGBはガンマ補正がされていないためです。ちなみに、ガンマ補正値に2.2より大きな数を入力すると全体が濃い色に小さな数を入力すると薄い色になります。

4 「マッピング 回転」の調整


「マッピング 回転」でYに90°を入力した様子


「マッピング 回転」でYに90°を入力した様子(上から)

この事例では「マッピング 回転」にY:90°を入力し、私が望むようなカラーランプ軸を設定しました。

5 「波テクスチャ スケール」の調整


「波テクスチャ スケール」の値に3を入力した様子

「波テクスチャ スケール」のデフォルト値5を3に変更してみました。

「波テクスチャ スケール」の値は干渉色セットの繰り返し回数の係数です。

6 「波テクスチャ 位相オフセット」の調整


「波テクスチャ 位相オフセット」の値に0.2を入力した様子

「波テクスチャ 位相オフセット」のデフォルト値0を0.2に変更してみました。

「波テクスチャ 位相オフセット」の値は干渉色セットの始まる位置をずらす係数です。

7 感想メモ

やまだこーじさん開発の干渉色変換ツール機能に相当する機能を、今回Blenderで実現できたと考えます。

干渉色カラーランプの原型は2023.06.17記事「干渉色生成BlenderPythonスクリプトを作成して干渉色を楽しむ」で作成しましたが、今回新たに次の工夫を行いました。

・干渉色のガンマ補正

・「マッピング 回転」によるカラーランプ軸設定

・「波テクスチャ スケール」による干渉色セット繰り返し回数設定

・「波テクスチャ 位相オフセット」による干渉色セット始点設定

・作成ノード群とプリンシプルBSDFノードとのリンク

干渉色変換ツールを開発し、その情報を公開しているやまだこーじさんに感謝します。

なお、カラーランプを改変すれば、自由な配色セットによるオブジェクト塗色が可能となります。


2023年6月14日水曜日

BlenderのColorRampノードをBlenderPythonで遊ぶ

 Playing with Blender's ColorRamp node in BlenderPython


I played with Blender's ColorRamp node by getting its information with BlenderPython and generating a node set with BlenderPython. Operating ColorRamp has become fun.


BlenderのColorRampノードについて、その情報をBlenderPythonで取得したり、BlenderPythonでノードセットを生成したりして遊んでみました。ColorRampの操作が楽しくなってきました。

遊び 1 平面メッシュに干渉色カラーを塗るBlenderPythonスクリプト

2023.06.10記事「Blenderでカラーグラデーションを塗るPythonスクリプト」で、ChatGPTに「Blenderで新たな平面メッシュに赤~燈~黄~緑~青~藍~紫のカラーグラデーションを塗るPythonスクリプト」を作ってもらいました。

その回答に続けて、さらに次の質問をChatGPTにして回答を得ました。

【ChatGPT質問】

このBlenderPythonスクリプトを参考にして、Blenderで新たな平面メッシュに干渉色カラーのグラデーションを塗るスクリプトを教えてください。

【ChatGPT回答】

……………………………………………………………………

import bpy

# 平面メッシュ生成とマテリアル設定、ノードを使用、ブレンドモードをアルファブレンドに設定

bpy.ops.mesh.primitive_plane_add()

obj = bpy.context.object

mat = bpy.data.materials.new(name="interference_color")

obj.active_material = mat

mat.use_nodes = True

mat.blend_method = "BLEND"

# テクスチャ座標設定

ndtc = mat.node_tree.nodes.new("ShaderNodeTexCoord")

ndtc.location = -800, 250

# マッピング設定

ndmp = mat.node_tree.nodes.new("ShaderNodeMapping")

ndmp.location = -630, 250

# グラデーションテクスチャ設定

ndgr = mat.node_tree.nodes.new("ShaderNodeTexGradient")

ndgr.location = -450, 250

# カラーランプ設定

ndvr = mat.node_tree.nodes.new("ShaderNodeValToRGB")

ndvr.location = -260, 250

ndvr.color_ramp.color_mode = "RGB"

ndvr.color_ramp.interpolation = "LINEAR"

# 干渉色カラーグラデーションを設定

ndvr.color_ramp.elements[0].position = 0.0

ndvr.color_ramp.elements[0].color = 1, 0, 0, 1

ndvr.color_ramp.elements.new(position=0.25).color = 1, 0.4, 0, 1

ndvr.color_ramp.elements.new(position=0.5).color = 0, 1, 0, 1

ndvr.color_ramp.elements.new(position=0.75).color = 0, 0, 1, 1

ndvr.color_ramp.elements.new(position=1.0).color = 1, 0, 1, 1

# プリンシプルBSDF設定

ndpb = mat.node_tree.nodes["Principled BSDF"]

ndpb.inputs[0].default_value = 0, 0, 0, 1

ndpb.inputs[7].default_value = 0

ndpb.inputs[9].default_value = 1

ndpb.inputs[17].default_value = 0

ndpb.inputs[18].default_value = 1

# ノード間のリンク設定

mat.node_tree.links.new(ndtc.outputs[0], ndmp.inputs[0])

mat.node_tree.links.new(ndmp.outputs[0], ndgr.inputs[0])

mat.node_tree.links.new(ndgr.outputs[0], ndvr.inputs[0])

mat.node_tree.links.new(ndvr.outputs[0], ndpb.inputs[0])

……………………………………………………………………

【ChatGPT説明】

このスクリプトは、干渉色カラーグラデーションを作成するために、いくつかのノードを追加し、カラーランプの要素を調整しています。干渉色カラーグラデーションは、赤、橙、黄、緑、青、紫の色相で構成されます。

新たな平面メッシュを作成し、その上に干渉色カラーグラデーションが適用されます。干渉色カラーグラデーションは、物体の位置に依存しないため、平面メッシュのサイズや形状に関係なく同じグラデーションが得られます。

このスクリプトを実行すると、新しい平面メッシュが作成され、その上に干渉色カラーグラデーションが塗られます。


干渉色に塗られた平面

やまだこーじさん開発の干渉色とはだいぶ趣が違いますが、ChatGPTなりに干渉色の事例を作ったことは楽しいできごとです。

関連して、次のような追加質問をしてみました。

【ChatGPT質問】

このスクリプトで表現した「干渉色」の定義や説明を教えてください。

【ChatGPT回答】

「干渉色」とは、物理的な干渉現象に基づいて生じる色のことを指します。光は波動の性質を持っており、波長や振動数の異なる光が干渉することで、特定の色の組み合わせが生じます。

干渉色は、光の波長や周波数によって変化し、視覚的な色の現象として観察されます。一般的に、光の干渉は2つの波が出会って相互作用する場合に起こります。

例えば、薄い膜の上を透過した光が反射して戻ってくる場合、波の干渉によって一部の波長の光が強められたり減衰したりすることがあります。この干渉によって生じる光の波長の組み合わせが、干渉色として観察されます。

具体的な例としては、オイルや水の薄い膜の上に光が反射して干渉色が現れる現象や、CDやDVDの表面の微細な凹凸が光の干渉によって虹色の光を生じる現象などがあります。

干渉色は一般的には虹色に似た色相を持ち、複数の色が連続的に変化するグラデーションを形成します。このスクリプトでは、赤、橙、黄、緑、青、紫の干渉色のグラデーションが平面メッシュに塗られるように設定されています。

…………………

ChatGPTとコミュニケーションが成り立ったことは楽しいことです。

遊び 2 ColorRampノードの情報取得スクリプト作成

遊び1でChatGPTに作ってもらった干渉色グラデーションのColorRampノードをテスト事例として、そのノードから詳細情報を取得するBlenderPythonスクリプトをChatGPTの支援を受けて作りました。

……………………………………………………………………

#選択されたカラーランプノードのcolor_mode,interpolation,各要素の番号,position,color(BlenderにおけるRGB表記、0.0-1.0の範囲で表示)をprintする

import bpy

# カラーランプノードを取得

selected_node = bpy.context.active_object.active_material.node_tree.nodes.active

# カラーモードを出力

color_mode = selected_node.color_ramp.color_mode

print("Color Mode:", color_mode)

# 補間方法を出力

interpolation = selected_node.color_ramp.interpolation

print("Interpolation:", interpolation)

# カラーランプの各要素の情報を出力

elements = selected_node.color_ramp.elements

for i, element in enumerate(elements):

    position = element.position

    color = element.color

    # BlenderにおけるRGB表記に変換

    color_blender = (

        color[0],

        color[1],

        color[2]

    )

    print(f"Element {i} - Position: {position}, Color: {color_blender}")

……………………………………………………………………


スクリプトを走らせた結果得られたColorRampノード情報

複雑で手の込んだColorRampノードをアナログで作成した場合、positionやcolor(RGB値、0.0-1.0の範囲)の数値は桁の多い少数点表示になりますからその記録をする上で、このBlenderPythonスクリプトがあると便利です。ColorRampをアペンドしなくても、数値でColorRampを再生できます。色をRGB値(0-255)表示と16進数表示のスクリプトも別に作成しました。

遊び 3 ColorRampノードセット生成スクリプト作成

遊び2で得られたColorRampノード情報をテスト事例として、ColorRampノードと関連ノードをセットで生成して、シェーダーエディター画面に配置するBlenderPythonスクリプトをChatGPTの支援を受けて作成しました。

……………………………………………………………………

#ColorRampノードセット(テクスチャ座標、マッピング、グラデーションテクスチャ、カラーランプ)の生成

import bpy

# 選択されたオブジェクトを取得

selected_obj = bpy.context.object

# オブジェクトに関連付けられたマテリアルを取得

material = selected_obj.active_material

# マテリアルが存在しない場合は新しいマテリアルを作成

if material is None:

    material = bpy.data.materials.new(name="interference_color")

    selected_obj.active_material = material

    material.use_nodes = True

    material.blend_method = "BLEND"

# テクスチャ座標設定

ndtc = material.node_tree.nodes.new("ShaderNodeTexCoord")

ndtc.location = -800, 350

# マッピング設定

ndmp = material.node_tree.nodes.new("ShaderNodeMapping")

ndmp.location = -630, 350

# グラデーションテクスチャ設定

ndgr = material.node_tree.nodes.new("ShaderNodeTexGradient")

ndgr.location = -450, 350

# カラーランプノードの追加と設定

ndvr = material.node_tree.nodes.new("ShaderNodeValToRGB")

ndvr.location = -260, 350

ndvr.color_ramp.color_mode = "RGB"

ndvr.color_ramp.interpolation = "LINEAR"

# 干渉色カラーグラデーションの設定

ndvr.color_ramp.elements[0].position = 0.0

ndvr.color_ramp.elements[0].color = 1, 0, 0, 1

ndvr.color_ramp.elements.new(position=0.25).color = 1, 0.4, 0, 1

ndvr.color_ramp.elements.new(position=0.5).color = 0, 1, 0, 1

ndvr.color_ramp.elements.new(position=0.75).color = 0, 0, 1, 1

ndvr.color_ramp.elements.new(position=1.0).color = 1, 0, 1, 1

# ノード間のリンク設定

material.node_tree.links.new(ndtc.outputs[0], ndmp.inputs[0])

material.node_tree.links.new(ndmp.outputs[0], ndgr.inputs[0])

material.node_tree.links.new(ndgr.outputs[0], ndvr.inputs[0])

……………………………………………………………………


ColorRampノードセット生成スクリプトを走らせてセットを生成し、メッシュオブジェクトにリンクした様子


BlenderPythonスクリプトで生成したノードセット

このスクリプトがあれば、数値情報があれば、直ぐにColorRampノードを実戦投入できます。生成するノードセットはテクスチャ座標ノード、マッピングノード、グラデーションテクスチャノード、ColorRampノードです。

遊び 4 ColorRampノードのプロパティ画面でノードを拡大出来ることを知る

シェーダーエディター画面の中に通常のColorRampノードは拡大に限度があります。しかしシェーダーエディター画面右に生成できるColorRampノードのプロパティ画面ではColorRampをいくらでも拡大できます。多数のストップを配置する場合などに便利であることに気が付きました。


拡大したColorRampノードのプロパティ画面

感想

干渉色はやまだこーじさんが素晴らしいものを開発していますから、それを使わせていただくことにします。自分が学習している考古事象(考古学的地形、考古遺物など)を見やすくしたり、分析しやすくするのにふさわしいカラーグラデーションを開発して楽しむことにします。


2023年4月17日月曜日

ChatGPTでBlenderPythonのコード生成

 BlenderPython code generation with ChatGPT


I actually confirmed the information that ChatGPT can generate BlenderPython code and run Blender. Certainly, even without knowledge of BlenderPython, I was able to instruct ChatGPT in Japanese to generate code and draw with Blender. I plan to use ChatGPT as a BlenderPython learning tool.


ChatGPTがBlenderPythonのコードを生成してBlenderを動かせるという情報を、実際に確かめてみました。確かにBlenderPythonの知識が無くても、日本語でChatGPTに指示してコードを生成して、Blenderで作画できました。自分はChatGPTをBlenderPython操作習得ツールとして使うつもりです。

1 最初の質問


最初の質問

2 ChatGPTの回答1


ChatGPTの回答1

3 ChatGPT回答1でBlenderを動かす

ChatGPT回答1をBlenderのスクリプト画面にコピペして動かすと、エラーがでました。

4 エラーをChatGPTに伝える


エラーをChatGPTに伝えました。

5 ChatGPTの回答2


エラー指摘に対応したChatGPTの回答2

6 ChatGPT回答2でBlenderを動かす

ChatGPT回答2をBlenderのスクリプト画面にコピペして動かすと、作画できました。


ChatGPT回答2でBlenderが作画した様子

7 感想

BlenderPythonの知識が虚弱な自分にとってChatGPTは一種の救世主になりそうです。BlenderPython操作習熟の有用ツールとして使えそうです。

ChatGPTで質問を繰り返すことでエラーをなくすとともに、自分の求めるイメージとか、機能とかをBlenderPythonで作れるかもしれないという期待が湧いてきました。