
Blender×Pythonで3次元の格子点を作ってみた
(2021年9月20日 17:08 初出FB)
3次元の格子点を中から眺めたイメージ、できた! 地理院地図ファンクラブの共同主催者のIさんから「干渉色の立体中に飛び込むようなイメージ」の表現方法があるか、というご質問を某所でいただきました。。とても面白そうな「お題」をいただいたので、チャレンジ中。
まずは、Pythonを使い、Blenderで(x,y,z)の格子点に球を沢山配置して、中心の格子点の近くから眺めた様子が上の画像と下の画像です。
あとは、ランダム色の配色を、各格子点のデータに応じて干渉色にしたら完成かも。。干渉色のRGB値の算出アルゴリズムは、すでにPythonで過去に作ったのがあるので、それを組み込めばOK。。今回のPythonのスクリプトは下記のとおりです。「ランダム色の600匹のサル」のスクリプトを改造してます。
# Draw uv_spheres in random colors on 3D glid-points in Blender using Python
# Pythonを使ってBlenderで格子点上にランダムの色で描く
import bpy
from random import randint
import numpy as np
# "def HSL_2_RGB" and "def Hue_2_RGB" ported "HSL → RGB"
# from https://www.easyrgb.com/en/math.php to Python.
def HSL_2_RGB(H, S, L): # Function to convert HLS to RGB
# H, S and L input range = 0 - 1.0
# R, G and B output range = 0 - 1.0 # Changed 255 to 1.0
if S == 0 :
R = L * 1.0 # Changed 255 to 1.0
G = L * 1.0 # Changed 255 to 1.0
B = L * 1.0 # Changed 255 to 1.0
else:
if L < 0.5 : var_2 = L * ( 1 + S )
else : var_2 = ( L + S ) - ( S * L )
var_1 = 2 * L - var_2
R = 1.0 * Hue_2_RGB( var_1, var_2, H + ( 1 / 3 ) ) # Changed 255 to 1.0
G = 1.0 * Hue_2_RGB( var_1, var_2, H ) # Changed 255 to 1.0
B = 1.0 * Hue_2_RGB( var_1, var_2, H - ( 1 / 3 ) ) # Changed 255 to 1.0
return R, G, B
def Hue_2_RGB( v1, v2, vH ): # Function to convert Hue to RGB
if vH < 0 : vH += 1
if vH > 1 : vH -= 1
if 6 * vH < 1 : return ( v1 + ( v2 - v1 ) * 6 * vH )
if 2 * vH < 1 : return ( v2 )
if 3 * vH < 2 : return ( v1 + ( v2 - v1 ) * ( ( 2 / 3 ) - vH ) * 6 )
return ( v1 )
def materialRandomColor(materialName='') : # Function to make material
material = bpy.data.materials.new(materialName)
material.use_nodes = True
p_BSDF = material.node_tree.nodes["Principled BSDF"]
R, G, B = HSL_2_RGB(np.random.rand(1), 1.0, 0.5) # Get RGB values of H = 0-1(random), S = 1, L = 0.5
p_BSDF.inputs[0].default_value = (R, G, B, 1) # RGBA
p_BSDF.inputs[7].default_value = 0.05 # Roughness
p_BSDF.inputs[15].default_value = 0.8 # Transmittance
return material
# Add uv_spheres on 3D glid-points
number = 5
spaceRange = 50
for k in range(-number, number + 1, 1):
for j in range(-number, number + 1, 1):
for i in range(-number, number + 1, 1):
x = i * spaceRange / ( 2 * number )
y = j * spaceRange / ( 2 * number )
z = k * spaceRange / ( 2 * number )
materialName = 'Color' + str(i+j*10+k*100)
material = materialRandomColor(materialName)
bpy.ops.mesh.primitive_uv_sphere_add(location=(x,y,z))
bpy.context.object.data.materials.append(material)