__author__ = 'thoth'
import bpy
from mathutils import *
from math import *
def find_or_create_node(nodes, type):
for n in nodes:
if n.type == type:
return n
return nodes.new(type)
def get_or_create_node(name, mat, type):
rval = mat.node_tree.nodes.get(name)
if rval is None:
rval = mat.node_tree.nodes.new(type)
rval.name = name
return rval
def rig_material_nodes( mat, spots):
mat.use_nodes = True
geom_node = find_or_create_node(mat.node_tree.nodes, 'GEOMETRY')
post_scale = get_or_create_node("geometric scale", mat, 'ShaderNodeValue')
post_scale.location = (-200,200)
if post_scale.outputs[0].default_value<=0:
post_scale.outputs[0].default_value = 1
layer = []
for i in range(len(spots)):
spot = spots[i]
y = i*200
cs_name = 'group %d' % i
convert_space = mat.node_tree.nodes.get(cs_name)
if convert_space is None:
convert_space = mat.node_tree.nodes.new('ShaderNodeGroup')
convert_space.name = cs_name
convert_space.node_tree = bpy.data.node_groups['convert space']
convert_space.location = [0, y]
mat.node_tree.links.new(convert_space.inputs['xyz'], geom_node.outputs['Orco'])
convert_space.inputs['x axis'].default_value = spot["x axis"]
convert_space.inputs['y axis'].default_value = spot["y axis"]
convert_space.inputs['z axis'].default_value = spot["z axis"]
mat.node_tree.links.new(convert_space.inputs[-1], post_scale.outputs[0])
t_name = "texture %d"%i
tex_node = mat.node_tree.nodes.get(t_name)
if tex_node is None:
tex_node = mat.node_tree.nodes.new("ShaderNodeTexture")
tex_node.name = t_name
tex_node.texture = bpy.data.textures[spot['texture name']]
tex_node.location = [200, y]
tex_node.hide = True
mat.node_tree.links.new(tex_node.inputs[0], convert_space.outputs[0])
layer.append({ 'cs': convert_space.outputs[1],
'tex': tex_node,
'tex_output' : tex_node.outputs[1]} )
column=1
x=200
while 1 < len(layer):
new_layer = []
factor = 2**column
for i in range(ceil(len(layer) /2)):
y = (i + 0.5) * factor * 200
if i*2+1 < len(layer) :
comparison_name = "comparison %d,%d"%(factor,i)
comparison_node = get_or_create_node(comparison_name, mat, "ShaderNodeMath")
comparison_node.operation = 'GREATER_THAN'
comparison_node.location = [x, y]
comparison_node.hide = True
mat.node_tree.links.new(comparison_node.inputs[1], layer[i*2]['cs'])
mat.node_tree.links.new(comparison_node.inputs[0], layer[i*2+1]['cs'])
min_name = "min %d,%d"%(factor,i)
min_node = get_or_create_node(min_name, mat, "ShaderNodeMath")
min_node.operation = 'MINIMUM'
min_node.location = [x, y -50]
min_node.hide = True
mat.node_tree.links.new(min_node.inputs[1], layer[i*2]['cs'])
mat.node_tree.links.new(min_node.inputs[0], layer[i*2+1]['cs'])
mix_node = get_or_create_node("mix %d,%d"%(factor,i), mat, 'ShaderNodeMixRGB')
mix_node.location = [ x+150, y + 50]
mix_node.hide = True
mat.node_tree.links.new(mix_node.inputs[0], comparison_node.outputs[0])
mat.node_tree.links.new(mix_node.inputs[2], layer[i*2]['tex_output'])
mat.node_tree.links.new(mix_node.inputs[1], layer[i*2+1]['tex_output'])
new_layer.append({ 'cs' : min_node.outputs[0],
'tex' : mix_node,
'tex_output': mix_node.outputs[0]
})
else:
new_layer.append( layer[i*2])
layer = new_layer
column = column+1
x = x+400
output_node = find_or_create_node(mat.node_tree.nodes, 'OUTPUT')
mat.node_tree.links.new(output_node.inputs[0], layer[0]['tex_output'])
def spot_of(normal_vector, texture_name):
normal_vector = Vector(normal_vector).normalized()
x_axis_ = Vector([0, 0, 1]).cross(normal_vector)
if (x_axis_.magnitude==0) :
x_axis = Vector([0,1,0]).cross(normal_vector).normalized()
else:
x_axis = x_axis_.normalized()
y_axis = normal_vector.cross(x_axis)
return {
"x axis": x_axis,
"y axis": y_axis,
"z axis": normal_vector,
"texture name": texture_name
}
def axis_spots():
return [
# spot_of([0,1,0], "bacon"),
spot_of([0, -1, 0], "bacon"),
spot_of([1, 0, 0], "bacon"),
spot_of([-1, 0, 0], "bacon"),
spot_of([0, 0, 1], "bacon"),
spot_of([0, 0, -1], "bacon"),
]
spots = axis_spots()
def gcd(a,b):
a=abs(a)
b=abs(b)
lesser = min(a, b)
if lesser==0:
return 0
m = a%b
if m==0:
return lesser
return gcd(m, lesser)
def degenerate(x, y, z):
if gcd(gcd(x,y),z) >1:
return True
if x==0 and y==0 and z==0:
return True
return False
def coords_2Hz():
return [[x * 0.5, y * 0.5, z * 0.5] for x in range(-2, 3) for y in range(-2, 3) for z in range(-2, 3) if
not degenerate(x, y, z)]
if True:
if True:
coords = coords_2Hz()
else:
coords = [ [x,y,z] for x in range(-1,2) for y in range(-1,2) for z in range(-1,2) if not degenerate(x,y,z)]
print(len(coords))
spots = [ spot_of(co, "bacon") for co in coords]
rig_material_nodes( bpy.data.materials['exp1'], spots)
|
Blender python API quick-start
Syntax highlighting by Pygments.