2
$\begingroup$

I want to create a large set of spiral galaxies with textures using a python script.

I managed to create shader nodes and links to set up a material.

enter image description here

For the spiral shape, I need to perform a transformation of the standard uv-mesh. The transformation is written below. Basically, it is a proportional editing, where the center row of the rectangular mesh is grabbed and shifted horizontally.

enter image description here

bpy.ops.object.editmode_toggle()
bpy.ops.transform.translate(value=(1.03353, 0.00369117, 0), orient_type='GLOBAL', orient_matrix=((1, 0, 0), (0, 1, 0), (0, 0, 1)), orient_matrix_type='GLOBAL', mirror=True, use_proportional_edit=True, proportional_edit_falloff='SMOOTH', proportional_size=1, use_proportional_connected=False, use_proportional_projected=False)

How can I include this transformation in the python script? My script has the following structure:

 bpy.ops.mesh.primitive_uv_sphere_add(radius = 5, enter_editmode = False, location=(x,y,z))
 sphere = bpy.context.active_object
  
 sphere.data.materials.append(get_material(i))
 sphere.scale[2]=0.1

and the function get_material(index)

def get_material(index):
    mat = bpy.data.materials.new("GalaxyMaterial"+str(index))
 
    mat.use_nodes = True
    node_tree = mat.node_tree
    nodes = node_tree.nodes

    output = nodes.get("Material Output")
    bsdf = nodes.get("Principled BSDF") 

    links =mat.node_tree.links

    node_coord = nodes.new(type="ShaderNodeTexCoord")

    node_texture = nodes.new(type='ShaderNodeTexNoise')

    links.new(node_coord.outputs[2],node_texture.inputs[0])
    node_texture.inputs[2].default_value=18
    node_texture.inputs[3].default_value=5.3
    node_texture.inputs[4].default_value=0.567
    node_texture.inputs[5].default_value=1.1

    node_ramp = nodes.new(type='ShaderNodeValToRGB')

    node_ramp.color_ramp.elements[0].color = (0,0,0,1)
    node_ramp.color_ramp.elements[0].position=0.45
    node_ramp.color_ramp.elements[1].position=0.7
    node_ramp.color_ramp.elements[1].color = (1,1,1,1)

    links.new(node_texture.outputs[0],node_ramp.inputs[0])
    links.new(node_ramp.outputs[0],bsdf.inputs[17])
    return mat
$\endgroup$
1
  • 1
    $\begingroup$ Are you trying to create a spiral transformation of a mesh? Textures could provide the spiral itself visually. You may want to show regular rectangular grid and the mesh transformed by a proportional edit rotation resulting in a spiral. I am not sure I understand why translation would be your goal. Since the question involves materials or textures you may want to specify whether the texture has a static spiral motif or you intend to create a uv map with a spiral motif. You may want to place a question mark on your question (???) Please show images if possible. $\endgroup$ May 25 '21 at 18:17
1
$\begingroup$

I was not able to apply the transformation

bpy.ops.transform.translate(value=(1.03353, 0.00369117, 0), orient_type='GLOBAL', orient_matrix=((1, 0, 0), (0, 1, 0), (0, 0, 1)), orient_matrix_type='GLOBAL', mirror=True, use_proportional_edit=True, proportional_edit_falloff='SMOOTH', proportional_size=1, use_proportional_connected=False, use_proportional_projected=False)

to the uv-mesh. Blender only applies this transformation to the active element.

Instead, it is possible to rotate the mesh manually. To obtain the proportional rotation, I rotated the mesh depending on the radius of the mesh point.

import bpy
import math
import numpy as np
import random
import bpy
import mathutils
from mathutils import Vector,Quaternion

#make objects glow
bpy.context.scene.eevee.use_bloom = True
#make background black
bpy.data.worlds["World"].node_tree.nodes["Background"].inputs[0].default_value = (0, 0, 0, 1)



#delete all objects
bpy.ops.object.select_all(action='SELECT')
bpy.ops.object.delete(use_global=False)

#camera0
bpy.ops.object.camera_add(enter_editmode=False, align='VIEW', location=(20,0,0), rotation=(math.radians(90), math.radians(0), math.radians(90)))
camera = bpy.context.active_object

#sphere
bpy.ops.mesh.primitive_uv_sphere_add(segments = 30,ring_count=30,radius = 2, enter_editmode = False, location=(0,0,0))
galaxy = bpy.context.active_object
galaxy.scale[2]=0.1


mat = bpy.data.materials.new("GalaxyMaterial")

mat.use_nodes = True
node_tree = mat.node_tree
nodes = node_tree.nodes

output = nodes.get("Material Output")
bsdf = nodes.get("Principled BSDF") 

links =mat.node_tree.links

node_coord = nodes.new(type="ShaderNodeTexCoord")

node_texture = nodes.new(type='ShaderNodeTexNoise')

links.new(node_coord.outputs[2],node_texture.inputs[0])
node_texture.inputs[2].default_value=25
node_texture.inputs[3].default_value=5.3
node_texture.inputs[4].default_value=0.567
node_texture.inputs[5].default_value=1.1


node_ramp = nodes.new(type='ShaderNodeValToRGB')

node_ramp.color_ramp.elements[0].color = (0,0,0,1)
node_ramp.color_ramp.elements[0].position=0.45
node_ramp.color_ramp.elements[1].position=0.7
node_ramp.color_ramp.elements[1].color = (1,1,1,1)

links.new(node_texture.outputs[0],node_ramp.inputs[0])
links.new(node_ramp.outputs[0],bsdf.inputs[17])

def proportional_rotation(radius):
    return mathutils.Matrix.Rotation(math.radians(-200*radius), 4, 'Z')

# rotate vertices proportial to their distance from the origin
mesh = galaxy.data
for vert in mesh.vertices:
    r = math.sqrt(vert.co[0]*vert.co[0]+vert.co[1]*vert.co[1])
    vert.co = proportional_rotation(r) @ vert.co


galaxy.data.materials.append(mat)

The result looks like: enter image description here

$\endgroup$

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.