Skip to content

Latest commit

 

History

History
149 lines (124 loc) · 5.75 KB

File metadata and controls

149 lines (124 loc) · 5.75 KB
Error in user YAML: (<unknown>): found a tab character that violate indentation while scanning a plain scalar at line 3 column 3
---
- oeasy Python 0735
- 这是 oeasy 系统化 Python 教程,从基础一步步讲,扎实、完整、不跳步。愿意花时间学,就能真正学会。
- 本教程同步发布在: 
	- 个人网站: `https://oeasy.org` 
	- 蓝桥云课: `https://www.lanqiao.cn/courses/3584` 
	- GitHub: `https://github.com/overmind1980/oeasy-python-tutorial` 
	- Gitee: `https://gitee.com/overmind1980/oeasypython` 
---
import bpy
import bmesh
from math import radians, cos, sin

data_list = [bpy.data.meshes, bpy.data.materials]
for i in range(len(data_list)):
    list = data_list[i].values()
    for j in range(len(list)):
        data_list[i].remove(list[j])

def set_material(obj):
    mat = bpy.data.materials.new('material')
    obj.data.materials.append(mat)
    mat.use_nodes = True
    
    if 'Principled BSDF' in mat.node_tree.nodes:
        shader_Principled_BSDF = mat.node_tree.nodes['Principled BSDF']
    else:
        shader_Principled_BSDF = mat.node_tree.nodes.new('ShaderNodeBsdfPrincipled')
    
    if shader_Principled_BSDF is None:
        print("Error: Could not create or find Principled BSDF node")
        return
    
    shader_Principled_BSDF.location = (500, 0)
    
    output = mat.node_tree.nodes.get('Material Output')
    if output is None:
        print("Error: Could not find Material Output node")
        return
    
    output.location = (800, 0)
    
    attribute = mat.node_tree.nodes.new('ShaderNodeAttribute')
    attribute.location = (0, 0)
    attribute.attribute_name = 'vert_color'
    
    color_ramp = mat.node_tree.nodes.new('ShaderNodeValToRGB')
    color_ramp.location = (200, 0)
    color_ramp.color_ramp.elements[0].color = (1.0, 0.0, 0.0, 1.0)
    color_ramp.color_ramp.elements[1].color = (0.0, 1.0, 0.0, 1.0)
    
    link = mat.node_tree.links.new
    link(attribute.outputs[0], color_ramp.inputs[0])
    link(color_ramp.outputs[0], shader_Principled_BSDF.inputs[0])
    link(shader_Principled_BSDF.outputs[0], output.inputs[0])
    
    # 插入颜色变化关键帧
    for frame in range(0, 401, 20):
        color_ramp.color_ramp.elements[0].color = (1.0, frame / 400.0, 0.0, 1.0)
        color_ramp.color_ramp.elements[1].color = (0.0, 1.0 - frame / 400.0, 0.0, 1.0)
        color_ramp.color_ramp.elements[0].keyframe_insert(data_path="color", frame=frame)
        color_ramp.color_ramp.elements[1].keyframe_insert(data_path="color", frame=frame)

radius = 0.015
depth = 1
vertices = 6

bpy.ops.mesh.primitive_cylinder_add(vertices=vertices, radius=radius, depth=depth,
    location=(0, depth*cos(radians(30)), 0), rotation=(0, radians(90), 0))
unit = bpy.context.active_object
bpy.ops.object.shade_smooth()
bpy.ops.object.transform_apply(rotation=True)

bpy.ops.object.mode_set(mode='EDIT')
bm = bmesh.from_edit_mesh(unit.data)
color_layer = bm.verts.layers.color.new('vert_color')
for vert in bm.verts:
    vert[color_layer] = (vert.co.x/depth+0.5, 0.0, 0.0, 1.0)
bmesh.update_edit_mesh(unit.data)
bm.free()
bpy.ops.object.mode_set(mode='OBJECT')
set_material(unit)

unit.select_set(True)
for i in range(5):
    bpy.ops.object.duplicate_move_linked()
    duplicate = bpy.context.object
    duplicate.rotation_euler[2] = radians(60)*(i+1)

bpy.ops.object.select_all(action='SELECT')
bpy.ops.object.join()
hexagon = bpy.context.active_object
hexagon.name = 'hexagon'
bpy.ops.object.transform_apply()

hexagon.select_set(True)
hexagons = []
theta = 10

for i in range(20):
    bpy.ops.object.duplicate_move_linked()
    duplicate = bpy.context.object
    hexagons.append(duplicate)
    duplicate.rotation_euler[2] += radians(theta)
    duplicate.scale *= sin(radians(60))/sin(radians(120-theta))

for i, obj in enumerate(hexagons):
    frame_start = 1
    frame_step = 20  # 将步长加倍
    for f in range(theta):
        frame_end = frame_start + frame_step
        obj.keyframe_insert('rotation_euler', frame=frame_start)
        obj.keyframe_insert('scale', frame=frame_start)
        obj.animation_data.action.fcurves[0].extrapolation = 'LINEAR'
        obj.rotation_euler[2] -= radians(1)*(i+1)
        s = pow(sin(radians(60))/sin(radians(120-theta+f+1)), i+1)
        obj.scale = (s, s, s)
        obj.keyframe_insert('rotation_euler', frame=frame_end)
        obj.keyframe_insert('scale', frame=frame_end)
        obj.animation_data.action.fcurves[0].extrapolation = 'LINEAR'
        frame_start = frame_end
        frame_step *= 1.15

bpy.context.scene.frame_end = 400
bpy.context.scene.render.fps = 60

bpy.ops.object.camera_add(location=(0, 0, 4))
camera = bpy.context.object
camera.keyframe_insert(data_path="location", frame=1)
camera.location = (0, 0, 8)
camera.keyframe_insert(data_path="location", frame=200)
camera.location = (0, 0, 4)
camera.keyframe_insert(data_path="location", frame=400)

bpy.context.scene.camera = camera

  1. 清理数据为了确保场景干净,我们首先清理Blender中现有的网格和材质数据。这有助于避免任何旧数据干扰新的动画创建。
  2. . 设置材质为六边形设置材质,使其在动画过程中能够展示颜色变化。我们使用Blender的节点系统来创建和配置材质,并插入颜色变化的关键帧。
  3. 创建六边形单元创建一个六边形单元,并为其设置平滑阴影和顶点颜色。然后将其复制并旋转,形成一个完整的六边形。
    1. 创建旋转动画通过复制和旋转六边形,创建一个旋转动画。每个复制的六边形在动画过程中都会缩放和旋转,形成一个动态的视觉效果。
    1. 设置摄像头动画为了更好地展示六边形的旋转动画,我们需要创建一个摄像头,并设置摄像头的动画,使其在场景中移动。摄像头将从远处开始,逐渐靠近六边形,然后再返回原位。

  • 本文来自 oeasy Python 系统教程。
  • 想完整、扎实学 Python,
  • 搜索 oeasy 即可。